审核日志插入

本文关键字:插入 日志 | 更新日期: 2023-09-27 18:00:52

我想知道是否有人能为插入的审计日志的实现提供一些输入。我需要确保它是事务性的。

我有一个基于以下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,比如Users,当我插入时,我想创建它,并在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(。

我希望将这两个点都保留在一个事务中,而不是将项目拆分为两个事务,即先保留用户帖子,然后再保留审核,因为审核可能会失败。

审核日志插入

覆盖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; }
}

如果您不介意在Audit表中添加对Post的可为null的引用,您可以让EF为您做这项工作。删除EntityId属性并添加到Audit:

public Post Post {get; set;}

当你记录事件时:

audit.Post = Post;

EF将插入Post,获取其ID,并在同一交易中为您添加对Audit的引用。我们在自己的AuditEvent模型中做这件事,我们对各种类型有几个可为null的引用,因此对于任何给定的事件,我们都可以链接回相关的一个或多个对象。