2011-06-30 14 views
1

誰かが挿入用の監査ログの実装のためにいくつかの入力を提供できるかどうか疑問に思っていました。私はトランザクションであることを保証する必要があります。監査ログの挿入

は、私は、次のPOCO上に構築された監査DbSetあります

public class Audit { 
    public int Id { get; set; } 
    public User User { get; set; } 
    public DateTime Created { get; set; } 
    public string Type { get; set; } 
    public int EntityId { get; set; } 
    public string Message { get; set; } 
} 

私が持っているDbSetを、ユーザーが私は挿入を行うときに、私は自動的に作成する監査DbSetに監査エンティティを追加することを、言います。なく、作成 ユーザ ポストの識別には、この例では

//var user = new User(); 
//user.Created = DateTime.Now; 
//user.Username = "testuser"; 
//user.Password = "testpassword"; 
//dataContext.Users.Add(user); 

var post = new Post(); 
post.Created = DateTime.Now; 
post.Title = "A sample post"; 
post.Published = true; 
post.Body = "Some content goes in here..."; 

dataContext.Posts.Add(post); 

var audit = new Audit(); 
audit.Created = DateTime.Now; 
audit.User = CurrentUser.User; // Currently logged in user 
audit.Type = "Post.Add"; 
audit.EntityId = post.Id; 
audit.Message = "New post was created"; 

dataContext.Audits.Add(audit); 

dataContext.SaveChanges(); 

、監査エンティティが追加されるが、「実体識別子」プロパティが0(デフォルト値)に設定される次のコードを検討すなわち、アイデンティティ値(SCOPE_IDENTITY()/ @@ IDENTITY)。

アイテムを2つのトランザクションに分割するのではなく、1つのトランザクションで両方のポイントを保持したいとします。つまり、 ユーザー を最初に投稿し、次に監査を続行してください。

+0

DBにaudit.Userに保存されたばかりですか?私はそれが新しいユーザーの本当のIDだと賭けています。 –

+0

audit.Userでは、現在ログインしているユーザーへの参照をアプリケーション(ASP.NET MVC)に保存しています。その方法で、システム上のアクションを誰が実行したのか、そして日時を追跡できます。 – benno

+0

Ah、gotcha ... Answer pending –

答えて

2

DbContext.SaveChanges()をオーバーライドし、すべてのChangeTracker.Entries()を参照してください(e => e.State!= EntityState.Unchanged)。ここで

は私のR & Dプロジェクトからの例です:

public override int SaveChanges() 
{ 
    int recordsUpdated = 0; 

    var journalEntries = new List<AuditJournal>(); 

    foreach (var entry in this.ChangeTracker.Entries<ITrackedEntity>().Where(e=>e.State != EntityState.Unchanged)) 
    { 
     AuditJournal journal = new AuditJournal(); 
     journal.Id = Guid.NewGuid(); 
     journal.EntityId = entry.Entity.Id.Value; 
     journal.EntityType = entry.Entity.EntityType; 
     journal.ActionType = entry.State.ToString(); 
     journal.OccurredOn = DateTime.UtcNow; 
     //journal.UserId = CURRENT USER 
     //journal.PreviousEntityData = XML SERIALIZATION OF ORIGINAL ENTITTY 

     journalEntries.Add(journal); 
    } 

    using (var scope = new TransactionScope()) 
    { 
     recordsUpdated = base.SaveChanges(); 

     foreach (var journalEntry in journalEntries) 
      this.AuditJournal.Add(journalEntry); 

     base.SaveChanges(); //Save journal entries 

     scope.Complete(); 
    } 

    return recordsUpdated; 
} 

//Every entity that needs to be audited has to implement this interface 
public interface ITrackedEntity 
{ 
    string EntityType { get; } 
    Guid? Id { get; set; } 
} 
+0

あなたの例Bryanのおかげで - 私の同僚が見ていたルートに似ていますが、Xmlのシリアライゼーションは考慮されていませんでしたが、私は確信しています... – benno

0

あなたの監査テーブルへの投稿にnull値の参照を追加しても構わない場合は、EFがあなたのために働くようにすることができます。実体識別子プロパティを削除し、監査に追加します。

public Post Post {get; set;} 

としたときにイベントを記録:

audit.Post = Post; 

EFは、ポストを挿入し、そのIDを取得し、同じであなたのために監査するために参照を追加しますトランザクション。私たちは独自のAuditEventモデルでこのようなことを行います。さまざまなタイプのnullable参照をいくつか持っていますので、任意のイベントで関連するオブジェクトにリンクすることができます。

+0

私はこれを考えていましたが、残念ながら私は約30のエンティティタイプを持っていますので、Auditには30種類のプロパティが必要です。 – benno

関連する問題