繁体   English   中英

如何记录更新<t> (列表<t> ) 使用 Audit.net 作为多个审计记录</t></t>

[英]How to log Update<T>(IList<T>) action as multiple audit records using Audit.net

我必须更新表中的批量记录。 我这样做如下。

BaseRepository.cs

    public IList<T> Update<T>(IList<T> instance) where T : class
    {
        IList<T> insertedItems = new List<T>();
        int totalCount = instance.Count;
        int count = 0;

        foreach (var item in instance)
        {
            insertedItems.Add(Update(item, count == (totalCount - 1)));
            count++;
        }

        try
        {
            context.SaveChanges();
        }
        catch (DbEntityValidationException ex)
        {
            //HandleDbEntityValidationException(ex);
        }
        //
        return insertedItems;
    }

测试方法

    public bool TestUpdate()
    {
        try
        {
            List<Test> list = new List<Test>();
            Test test1 = new Test();
            test1.Id = 3;
            test1.Message = "test string updated 40";
            Test test2 = new Test();
            test2.Id = 4;
            list.Add(test1); list.Add(test2);
            test2.Message = "test string updated 7";
            _repository.Update<Test>(list);
            this.unitOfWork.Save();
        }
        catch (Exception ex)
        {

        }
        finally
        {
            this.unitOfWork.Dispose();
        }
        return true;
    }

然后想用Audit.net做日志审计。 我做了如下...

全局.asax.cs

    Audit.Core.Configuration.DataProvider = new SqlDataProvider()
        {
            ConnectionString = "Data Source=FTD-NB-MADHARA;Initial Catalog=TestAuditTrail;User ID=sctavp_user;Password=welcome@123;MultipleActiveResultSets=true",
            Schema = "dbo",
            TableName = "Event",
            IdColumnName = "EventId",
            JsonColumnName = "JsonData",

            CustomColumns = new List<CustomColumn>()
        {
            new CustomColumn("UserName", ev=> ev.Environment.UserName.ToString()),
            new CustomColumn("MachineName", ev=> ev.Environment.MachineName.ToString()),
            new CustomColumn("DomainName", ev=> ev.Environment.DomainName.ToString()),
            new CustomColumn("ModuleName", ev => "AuditTrail"),
            new CustomColumn("CallingMethod", ev=> ev.Environment.CallingMethodName.ToString()),
            new CustomColumn("DatabaseName", ev=> ev.GetEntityFrameworkEvent().Database.ToString()),
            new CustomColumn("SchemaName", ev=> ev.GetEntityFrameworkEvent().Entries[0].Schema.ToString()),
            new CustomColumn("TableName", ev=> ev.GetEntityFrameworkEvent().Entries[0].Table.ToString()),
            new CustomColumn("Action", ev=> ev.GetEntityFrameworkEvent().Entries[0].Action.ToString()),}};

上下文变化

    private static DbContextHelper _helper = new DbContextHelper();
    private readonly IAuditDbContext _auditContext;

    public AuditTrailContext() : base("ApplicationDatabase")
    {
        //AuditDataProvider = new NullDataProvider();
        _auditContext = new DefaultAuditContext(this);
        _helper.SetConfig(_auditContext);
        
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Add(new DecimalPrecisionAttributeConvention());
    }

    #region without AuditDbContext
    public override int SaveChanges()
    {
        return _helper.SaveChanges(_auditContext, () => base.SaveChanges());
    }

    public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken))
    {
        return await _helper.SaveChangesAsync(_auditContext, () => base.SaveChangesAsync(cancellationToken));
    }

结果

JsonData 字段

    {"EventType":"DefaultAuditContext","Environment":{"UserName":"MadharaU","MachineName":"FTD-NB-MADHARA","DomainName":"BRANDIXLK","CallingMethodName":"Rocky.AuditService.Data.EntityManager.BaseRepository.Update()","AssemblyName":"Rocky.AuditService.Data.EntityManager, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null","Culture":"en-US"},"StartDate":"2021-02-23T03:52:47.0005326Z","EndDate":"2021-02-23T03:52:47.0371697Z","Duration":37,"EntityFrameworkEvent":{"Database":"AuditTrail","Entries":[{"Schema":"dbo","Table":"Test","Action":"Update","PrimaryKey":{"Id":3},"Changes":[{"ColumnName":"Message","OriginalValue":"test string updated 39","NewValue":"test string updated 40"}],"ColumnValues":{"Id":3,"Message":"test string updated 40"},"Valid":true,"ValidationResults":[]},{"Schema":"dbo","Table":"Test","Action":"Update","PrimaryKey":{"Id":4},"Changes":[{"ColumnName":"Message","OriginalValue":"test string updated 6","NewValue":"test string updated 7"}],"ColumnValues":{"Id":4,"Message":"test string updated 7"},"Valid":true,"ValidationResults":[]}],"Result":2,"Success":true}}

现在我的问题是,我同时更新了两条记录。 Audit.NET 已将两者作为单个记录记录在审计表中。 有什么方法可以分别为这两个更新插入日志详细信息。

你至少有两个选择

使用实体框架数据提供者

如果您可以将审计日志表 map 转换为 Entity Framework DbContext(它可以与您正在审计的 DbContext 相同或不同),那么您可以使用EntityFramework 数据提供程序而不是 SQL 数据提供程序。

例如,假设您有一个映射到 DbContext 的 AuditLog 表:

public class AuditLog
{
    public int Id { get; set; }
    public DateTime Date { get; set; }
    public string User { get; set; }
    public string Table { get; set; }
    public string JsonData { get; set; }
}
public class LogsDbContext : DbContext
{
    public DbSet<AuditLog> AuditLogs { get; set; }
    //...
}

然后您可以设置 EF 数据提供程序以将每个审核条目记录到 AuditLog 表上的记录中:

Audit.Core.Configuration.Setup()
    .UseEntityFramework(config => config
        .UseDbContext<LogsDbContext>()
        .AuditTypeMapper(_ => typeof(AuditLog))
        .AuditEntityAction<AuditLog>((ev, entry, auditLog) =>
        {
            auditLog.Date = DateTime.UtcNow;
            auditLog.Table = entry.Table;
            auditLog.User = ev.Environment.UserName;
            auditLog.JsonData = entry.ToJson();
        })
        .IgnoreMatchedProperties(true));

使用自定义 SQL 数据提供程序

继承自 SqlDataProvider,覆盖 Insert/InsertAsync 以触发每个实体条目的保存:

public class SingleSqlProvider : SqlDataProvider
{
    public SingleSqlProvider(Action<ISqlServerProviderConfigurator> config) : base(config) { }

    public override object InsertEvent(AuditEvent auditEvent)
    {
        var efEvent = auditEvent as AuditEventEntityFramework;
        object lastId = null;
        if (efEvent != null)
        {
            foreach (var entry in efEvent.EntityFrameworkEvent.Entries)
            {
                var clone = AuditEvent.FromJson<AuditEventEntityFramework>(auditEvent.ToJson());
                clone.EntityFrameworkEvent.Entries.Clear();
                clone.EntityFrameworkEvent.Entries.Add(entry);
                lastId = base.InsertEvent(clone);
            }
        }
        else
        {
            return base.InsertEvent(auditEvent);
        }
        return lastId;
    }

    public async override Task<object> InsertEventAsync(AuditEvent auditEvent)
    {
        // same but Async...
    }
}

那么设置可能是:

Audit.Core.Configuration.Setup()
    .UseCustomProvider(new SingleSqlProvider(config => config
        .ConnectionString("...")
        .TableName("...")));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM