2011-06-30 53 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(); 

在这种情况下,审计的单位将被添加,但“ENTITYID”属性将被设置为0(默认值),而不是创建 用户 后的身份,即身份值(SCOPE_IDENTITY()/ @@ IDENTITY)。

我想保持两个点在一个单一的交易,而不是分裂的项目为两项交易,即坚持在 用户 后,再坚持审计秒为有机会审计可能会失败。

+0

什么获得存储在audit.User在DB?我打赌这是新用户的真实ID。 –

+0

在audit.User中,我将对当前登录用户的引用存储到应用程序(ASP.NET MVC) - 这样我就可以跟踪在系统上执行操作的人员以及日期/时间。 – benno

+0

Ah,gotcha ...正在回答的问题 –

回答

2

覆盖DbContext.SaveChanges()并查看所有ChangeTracker.Entries()。其中​​(e => e.State!= EntityState.Unchanged)。

这里是我的A 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

如果您不介意将Post的可空引用添加到审计表中,则可以让EF为您完成工作。掉落的ENTITYID属性,并添加到审核:

public Post Post {get; set;} 

当你记录事件:

audit.Post = Post; 

EF将插入后,抓住它的ID,并添加在同一来审核你参考交易。我们在我们自己的AuditEvent模型中做了这件事,我们有几个可以为空的引用给我们的各种类型,所以对于任何给定的事件,我们可以链接回相关的对象或对象。

+0

我已经考虑过这个问题,但不幸的是我将会有大约30个实体类型,所以我不想在审计中拥有30个不同的属性,都是可以为空的。 – benno