我想知道是否有人可以为插入的审计日志记录实现提供一些输入。我需要确保它是交易性的。
我有一个基于以下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,比如用户,当我进行插入时,我想创建自动在Audit DbSet中添加一个Audit实体。请考虑以下代码:
//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)。
我想将这两个点保留在一个事务中,而不是将项目拆分为两个事务,即先保留 User Post,然后保持审计第二,因为有可能审计可能会失败。
答案 0 :(得分: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; }
}
答案 1 :(得分:0)
如果您不介意将Post的可引用引用添加到Audit表中,您可以让EF为您完成工作。删除EntityId属性并添加到Audit:
public Post Post {get; set;}
当你录制事件时:
audit.Post = Post;
EF将插入帖子,获取其ID并在同一事务中为您添加对Audit的引用。我们在自己的AuditEvent模型中做了这个确切的事情,我们对各种类型有几个可以为空的引用,因此对于任何给定的事件,我们都可以链接回相关的对象。