我正在使用Entity Framework 6,我正在使用EntityFramework Extended来执行一些批量更新和批量删除。批量更新和批量删除工作正常但是我还需要知道已更新/删除的实体(即当前和以前的值)。我认为使用EntityFramework.Extended提供的AuditLogger会向我提供更新或删除的实体的详细信息,但似乎并非如此。例如,使用下面的代码,即
var auditor =dbContext.BeginAudit();
dbContext.Addresses.Update(ent => new Address { AddressId = 1190 });
dbContext.SaveChanges();
var changes = auditor.LastLog;
这是简单的批量更新,可将所有addressId更新为1190
。
如果我检查changes.Entities
,它返回一个Count为0,即一个空列表。
我期待的是changes.Entities
在addressId更改为1190
之前将包含具有旧值的所有“旧”实体。
我错了还是这确实是正确的行为?如何在使用实体框架扩展批量更新/删除
时获取所有更新实体的审核日志由于
答案 0 :(得分:3)
您应启用审核员
var auditConfiguration = AuditConfiguration.Default;
auditConfiguration.IncludeRelationships = true;
auditConfiguration.LoadRelationships = true;
auditConfiguration.DefaultAuditable = true;
只需将其添加到初始化应用的位置,例如Global.asax.cs
<强>编辑强>
据我所知,您无法使用EF.Extended获取旧值。 这是我的解决方案:
覆盖上下文中的SaveChanges方法
public override int SaveChanges()
{
return SaveChanges(false);
}
public int SaveChanges(bool disableAudit)
{
var result = -1;
try
{
if (!disableAudit)
{
foreach (var entity in ChangeTracker.Entries().Where(x => x.State == EntityState.Added ||
x.State == EntityState.Modified ||
x.State == EntityState.Deleted))
{
ProccessAuditLog(entity);
}
}
}
catch (Exception ex)
{
// handle the ex here
}
finally
{
//save changes
result = base.SaveChanges();
}
return result;
}
并添加处理审计日志记录的方法:
private void ProccessAuditLog(DbEntityEntry entry)
{
var entity = entry.Entity;
var entityType = GetEntityType(entity.GetType());
var oldValue = Activator.CreateInstance(entityType); ;
if (entry.State == EntityState.Modified)
{
// entry.OriginalValues doesn't load navigation properties for changed entity so we should reload the object from db to get it
// save current values
var newValue = Activator.CreateInstance(entityType);
Mapper.DynamicMap(entity, newValue, entity.GetType(), entityType);
// reload old values for entity from the db
entry.Reload();
Mapper.DynamicMap(entry.Entity, oldValue, entity.GetType(), entityType);
// revert reloading changes in entity
entry.CurrentValues.SetValues(newValue);
entry.OriginalValues.SetValues(oldValue);
entry.State = EntityState.Modified;
entity = newValue;
}
if (entry.State == EntityState.Deleted)
{
// reload old values for entity from the db
entry.Reload();
Mapper.DynamicMap(entry.Entity, oldValue, entity.GetType(), entityType);
// revert reloading changes in entity
entry.OriginalValues.SetValues(oldValue);
entry.State = EntityState.Deleted;
entity = null;
}
// here is you can proccess old entity in 'oldValue' and new entity in 'entity'
// then save your log to db using SaveChanges(true) to prevent StackOverFlow exception
}
作为Mapper
,您可以使用AutoMapper
获取基本实体的类型代替代理类型的方法:
private Type GetEntityType(Type entityType)
{
return entityType.BaseType != null && entityType.Namespace == "System.Data.Entity.DynamicProxies"
? entityType.BaseType
: entityType;
}
希望它能帮到你