如何解决如何使用Audit.NET EntityFramework.Core为每个更改的属性编写审核日志条目
我正在尝试获取Audit:NET EntityFramework.Core扩展,以针对每个更改的属性写入AuditLog条目。
为此,我使用自定义的DataProvider覆盖了EntityFrameworkDataProvider.InsertEvent
。
问题是,使用DbContextHelper.Core.CreateAuditEvent
创建新的EntityFrameworkEvent返回null。
原因似乎是,这时在代码执行DbContextHelper.GetModifiedEntries
中确定所有EF条目都具有State.Unmodified
,即使它们明确包含在EventEntry更改中也是如此。
由于私有/内部属性,我试图通过手动创建内容来规避CreateAuditEvent。
也许我没有看到这个问题的替代解决方案,我愿意接受所有建议。
审计实体类
public class AuditLog
{
public int Id { get; set; }
public string Description { get; set; }
public string OldValue { get; set; }
public string NewValue { get; set; }
public string PropertyName { get; set; }
public DateTime AuditDateTime { get; set; }
public Guid? AuditIssuerUserId { get; set; }
public string Auditaction { get; set; }
public string TableName { get; set; }
public int TablePK { get; set; }
}
启动配置
Audit.Core.Configuration.Setup()
.UseCustomProvider(new CustomEntityFrameworkDataProvider(x => x
.AuditEntityAction<AuditLog>((ev,ent,auditEntity) =>
{
auditEntity.AuditDateTime = DateTime.Now;
auditEntity.Auditaction = ent.Action;
foreach(var change in ent.Changes)
{
auditEntity.OldValue = change.OriginalValue.ToString();
auditEntity.NewValue = change.NewValue.ToString();
auditEntity.PropertyName = change.ColumnName;
}
}
自定义数据提供程序类
public class CustomEntityFrameworkDataProvider : EntityFrameworkDataProvider
{
public override object InsertEvent(AuditEvent auditEvent)
{
var auditEventEf = auditEvent as AuditEventEntityFramework;
if (auditEventEf == null)
return null;
object result = null;
foreach (var entry in auditEventEf.EntityFrameworkEvent.Entries)
{
if (entry.Changes == null || entry.Changes.Count == 0)
continue;
foreach (var change in entry.Changes)
{
var contextHelper = new DbContextHelper();
var newEfEvent = contextHelper.CreateAuditEvent((IAuditDbContext)auditEventEf.EntityFrameworkEvent.GetDbContext());
if (newEfEvent == null)
continue;
newEfEvent.Entries = new List<EventEntry>() { entry };
entry.Changes = new List<EventEntryChange> { change };
auditEventEf.EntityFrameworkEvent = newEfEvent;
result = base.InsertEvent(auditEvent);
}
}
return result;
}
}
解决方法
在这里https://github.com/thepirat000/Audit.NET/issues/323#issuecomment-673007204
检查我的答案您无需调用CreateAuditEvent()
,您应该能够遍历原始事件的“更改”列表,并为每个更改调用base.InsertEvent()
,例如:
public override object InsertEvent(AuditEvent auditEvent)
{
var auditEventEf = auditEvent as AuditEventEntityFramework;
if (auditEventEf == null)
return null;
object result = null;
foreach (var entry in auditEventEf.EntityFrameworkEvent.Entries)
{
if (entry.Changes == null || entry.Changes.Count == 0)
continue;
// Call base.InsertEvent for each change
var originalChanges = entry.Changes;
foreach (var change in originalChanges)
{
entry.Changes = new List<EventEntryChange>() { change };
result = base.InsertEvent(auditEvent);
}
entry.Changes = originalChanges;
}
return result;
}
注意:
- 这可能会影响性能,因为每次列更改都会触发向数据库的插入。
- 如果您打算对DbContext.SaveChangesAsync使用异步调用,还应该在CustomDataProvider上实现InsertEventAsync方法
- “更改”属性仅可用于“更新”,因此,如果您还想审核插入和删除,则需要添加逻辑以从事件的ColumnValues属性中获取列值
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。