好的,这里发生了很多事情,我不想用一个冗长的代码样本来烦你们,所以这里有一个摘录.
当在我的EF上下文中调用SaveChangesAsync()时,我让它调用此方法来审计每个条目.
async Task Audit(DbEntityEntry<IAmAuditable> entry)
{
try
{
var newAuditEntry = new AuditEntry
{
EntityType = entry.Entity.GetType().Name,
Event = entry.State.ToString(),
SSOUserId = kernel.Get<User>().Id,
EntityId = entry.GetId().ToString(),
EventId = eventId
};如果所讨论的条目是实体创建,将导致在db上插入,那么我也这样做.
var properties = entry.CurrentValues.PropertyNames.Select(p => entry.Property(p)).ToList();
var addedValues = new List<AuditDataItem>();
foreach (var p in properties)
{
addedValues.Add(new AuditDataItem
{
PropertyName = p.Name,
PreviousValue = null,
NewValue = p.CurrentValue.ToString()
});
}
newAuditEntry.Changes = addedValues;
break;..。它就在这里倒下..。此时,对SaveChanges的基调用尚未执行,因此所涉实体还没有主键值.最终的结果是,我记录了一个没有主实体的实体的创建。
有没有人建议一个很好的、干净的方法来处理这个问题,这样我就可以将新的主键值输入到AuditDataItem中了?
编辑:
下面是我作为json记录的一个例子,这是一个AuditEntry对象和一些子AuditDataItem行的一部分.
{
"Id": 4,
"SSOUserId": 1,
"EventId": "6d862aad-0898-4794-aea0-00af6f2994ff",
"EntityType": "AC_Programme",
"Event": "Added",
"TimeOfEvent": "2016-02-04T12:04:31.5501508+01:00",
"Changes": [
{
"Id": 34,
"PropertyName": "Id",
"PreviousValue": null,
"NewValue": "0"
},
{
"Id": 35,
"PropertyName": "Name",
"PreviousValue": null,
"NewValue": "Test"
},
...
]
}发布于 2016-02-05 15:23:38
好吧,这就是我想出来的.很想知道你们是怎么想的。
public override async Task<int> SaveChangesAsync()
{
try
{
await AuditChanges(new[] { EntityState.Modified, EntityState.Deleted });
var result = await base.SaveChangesAsync();
await AuditChanges(new[] { EntityState.Added });
return result;
}
catch (DbEntityValidationException ex) { throw ConstructDetailsFor(ex); }
}
async Task AuditChanges(EntityState[] states)
{
var auditableEntities = ChangeTracker.Entries<IAmAuditable>()
.Where(e => states.Contains(e.State));
foreach (var entry in auditableEntities)
await Audit(entry);
}
async Task Audit(DbEntityEntry<IAmAuditable> entry)
{
...这是非常简单的:)
然后,我的审计方法基本上输入一个switch语句,并根据从变更跟踪器传入的可审计实体条目来决定运行什么逻辑。
我不认为审计能比这简单得多。
我将它放入一个泛型基类中,用于我的所有EF上下文,并运行一个迁移将其应用于所有db和bang .任何地方都可以对所有标记为"IAmAuditable“(空标记接口)的实体进行动态的自动审核。
我考虑使用一个属性,但这需要反射和什么不需要。
发布于 2016-02-05 10:40:12
据我所知,在对象被创建之后,没有任何事件可以调解对象的创建。有下列活动:
第一种情况发生在保存更改之前(与您遇到的问题相同)。第二种情况发生在查询或.Load结果从数据库中读取实体时,因此它不适合您的情况。
我能想到的唯一解决方案是覆盖原始的SaveChanges,并在重写的方法中这样做:
List<Object>中日志记录和拦截数据库操作(EF6以后)不适合你的需要
发布于 2016-02-05 13:34:23
您需要将ObjectStateEntry保存在AuditEntry中,然后重新访问在PostSaveChanges事件中主键为“临时”的每个AuditEntry。
下面是一个示例:
显然,我建议您在创建自己的库时使用EF+审核,但是如果您仍然希望对其进行编码,则库是开源的,因此您将能够找到大量的信息来帮助您。
免责声明:我是项目EF+ (EntityFramework Plus)的所有者
https://stackoverflow.com/questions/35221339
复制相似问题