使用Audit.EntityFramework

我try 在EventEntryChange对象的OriginalValue和NewValue属性中(可能也在ColumnValues对象中)设置相关实体的名称.我try 使用格式和覆盖选项,如下所示(只是为了显示它而简化的代码):

Audit.EntityFramework.Configuration.Setup()
    .ForContext<AppDbContext>(config => config
        .ForEntity<Product>(prodConfig =>
        {
            prodConfig.Format(x => x.ProductType, value =>
            {
                // Get name from related object
                var name = relatedObject?.Name;
                return name ?? value;
            });
        })
    );

在这两种情况下,它都会用更新后的值替换OriginalValue,但NewValue和ColumnValues条目将重置为外键ID.这是因为DbConextHelper中的代码:

    /// <summary>
    /// Updates column values and primary keys on the Audit Event after the EF save operation completes.
    /// </summary>
    public void UpdateAuditEvent(EntityFrameworkEvent efEvent, IAuditDbContext context)
    {
        // Update PK and FK
        foreach (var efEntry in efEvent.Entries)
        {
            var entry = efEntry.Entry;
            efEntry.PrimaryKey = GetPrimaryKey(context.DbContext, entry);
            foreach (var pk in efEntry.PrimaryKey)
            {
                if (efEntry.ColumnValues.ContainsKey(pk.Key))
                {
                    efEntry.ColumnValues[pk.Key] = pk.Value;
                }
            }
            var fks = GetForeignKeys(context.DbContext, entry);
            foreach (var fk in fks)
            {
                if (efEntry.ColumnValues.ContainsKey(fk.Key))
                {
                    efEntry.ColumnValues[fk.Key] = fk.Value;
                }

                var change = efEntry.Changes?.FirstOrDefault(e => e.ColumnName == fk.Key);
                if (change != null)
                {
                    change.NewValue = fk.Value;
                }
            }
        }
        // Update ConnectionId
        var clientConnectionId = TryGetClientConnectionId(context.DbContext);
        if (clientConnectionId != null)
        {
            efEvent.ConnectionId = clientConnectionId;
        }
    }

老实说,我真的不确定它为什么要对审计条目这样做,但我相信肯定有原因.然而,我仍然在试图弄清楚如何才能使日志(log)工作,或者甚至是类似的东西(例如,添加一个单独的更改来保存链接实体的名称),以满足我的需求.

推荐答案

如果在持久化实体之前ID是未知的,则需要使用UpdateAuditEvent方法,例如在数据库为插入生成ID的情况下.这就是库在保存实体后try 更新审核事件ID的原因.

一种 Select 是使用自定义的OnSving操作(就在保存审核事件之前发生)来更新属性.

例如:

Audit.Core.Configuration.AddOnSavingAction(scope =>
{
    foreach (var entry in scope.GetEntityFrameworkEvent().Entries)
    {
        if (entry.EntityType == typeof(Product))
        {
            entry.ColumnValues["ProductType"] = relatedObject.Name;
            foreach (var change in entry.Changes)
            {
                if (change.ColumnName == nameof(Product.ProductType))
                {
                    change.OriginalValue = relatedObject.Name;
                    change.NewValue = ...;
                }
            }
        }
    }
});

Csharp相关问答推荐

Blazor:用参数创建根路径

如何使用C#中的图形API更新用户配置文件图像

使用yaml将Azure函数代码部署到FunctionApp插槽时出现问题(zip未找到)

Blazor. NET 8—阶段启动配置文件不启动网站VS2022

与C#中的Zip列表并行

有没有办法在WPF文本框中添加复制事件的处理程序?

如何将MongoDB序列化程序设置为内部对象属性

在C#中有没有办法减少大型数组中新字符串的分配?

实体框架-IsRequired()与OnDelete()

是否可以在Entity Framework Core中使用只读 struct 作为拥有实体?

将C#类导入到PowerShell

使用可空引用类型时C#接口实现错误

多个参数的最小API删除

C#USB条形码 scanner 在第二次扫描时未写入行尾字符

如何在更新数据库实体时忽略特定字段?

如何对列表<;列表>;使用集合表达式?

如何处理ASP.NET Core中包含两个构造函数的控制器?

CsvHelper在第二次迭代时抛出System.ObjectDisposedException

C#LINQ多行条件

现在是否有一个.NET SDK等效于AsyncEx的AsyncLock?