如何从实体框架 6 中的 Auditlog 实体获取 id
Posted
技术标签:
【中文标题】如何从实体框架 6 中的 Auditlog 实体获取 id【英文标题】:How to get id from entity for Auditlog in Entity Framework 6 【发布时间】:2013-11-16 20:21:30 【问题描述】:我知道那里有几个类似的帖子,但我找不到任何可以解决此问题的帖子。
我想在 Entity Framework 6 中添加、更改或删除实体(软删除)时添加(某种)AudioLog。我已经覆盖了 SaveChanges,因为我只想为 EntityStates 添加、修改添加日志条目或已删除,我在第一次调用 SaveChanges 之前获取列表。问题是,因为我需要记录已执行的操作,所以我需要检查实体的 EntityState。但是在调用 SaveChanges 之后,EntityState 对于所有条目都是 Unchanged。
public override int SaveChanges()
using (var scope = new TransactionScope())
var modifiedEntries = ChangeTracker.Entries()
.Where(e => e.State == EntityState.Added || e.State == EntityState.Deleted || e.State == EntityState.Modified)
.ToList();
int changes = base.SaveChanges();
foreach (var entry in modifiedEntries)
ApplyAuditLog(entry);
base.SaveChanges();
scope.Complete();
return changes;
private void ApplyAuditLog(DbEntityEntry entry)
ILog entity = entry.Entity as ILog;
if (entity != null)
LogOperation operation;
switch (entry.State)
case EntityState.Added:
operation = LogOperation.CreateEntity;
break;
case EntityState.Deleted:
operation = LogOperation.DeleteEntity;
break;
case EntityState.Modified:
operation = LogOperation.UpdateEntity;
break;
default:
throw new ArgumentOutOfRangeException();
AuditLog log = new AuditLog
Created = DateTime.Now,
Entity = entry.Entity.GetType().Name,
EntityId = entity.Id,
Operation = operation,
;
AuditLog.Add(log);
【问题讨论】:
如果 id 是数据库生成的,那么您需要在SaveChanges()
调用之后检索它,因为之前的 id 根本不存在。
如果您查看代码,这正是我所做的。这不是问题,是在 SaveChanges 之后 EntityState 发生了变化。
对不起,我忽略了这一点。保存后 EntityState 将更改,因为 EntityState 不再添加或修改 - 它未修改。因此,如果您想保留 EntityState,则必须在保存之前存储该数据 - 并在保存后检索 id。
我知道。但我希望有人有一个很好的方法来解决这个问题。由于我在 SaveChanges() 之前没有 id,因此我无法弄清楚如何在第一个 SaveChanges() 之后将正确的 id 映射到正确的 AuditLog 对象。我需要依赖每个元素的索引位置吗?还是有更清洁的选择?如果是这样,请提供一个例子。
【参考方案1】:
啊……当然了!!对于新添加的实体,id 只会是一个“问题”,因此通过将列表分成两个(一个用于修改/删除,一个用于添加),我分两个阶段创建 AuditLog。
对于其他想要应用这种 AuditLog 的人,这是我的工作代码:
public override int SaveChanges()
using (var scope = new TransactionScope())
var addedEntries = ChangeTracker.Entries().Where(e => e.State == EntityState.Added).ToList();
var modifiedEntries = ChangeTracker.Entries().Where(e => e.State == EntityState.Deleted || e.State == EntityState.Modified).ToList();
foreach (var entry in modifiedEntries)
ApplyAuditLog(entry);
int changes = base.SaveChanges();
foreach (var entry in addedEntries)
ApplyAuditLog(entry, LogOperation.CreateEntity);
base.SaveChanges();
scope.Complete();
return changes;
private void ApplyAuditLog(DbEntityEntry entry)
LogOperation operation;
switch (entry.State)
case EntityState.Added:
operation = LogOperation.CreateEntity;
break;
case EntityState.Deleted:
operation = LogOperation.DeleteEntity;
break;
case EntityState.Modified:
operation = LogOperation.UpdateEntity;
break;
default:
throw new ArgumentOutOfRangeException();
ApplyAuditLog(entry, operation);
private void ApplyAuditLog(DbEntityEntry entry, LogOperation logOperation)
ILog entity = entry.Entity as ILog;
if (entity != null)
AuditLog log = new AuditLog
Created = DateTime.Now,
Entity = entry.Entity.GetType().Name,
EntityId = entity.Id,
Operation = logOperation,
;
AuditLog.Add(log);
【讨论】:
您可能希望将 SaveChanges 包装在 try/throw 中以捕获异常并退出审核条目。如果提交失败,审计条目不应该存在 其实添加时需要id,审计必须和原表相关,以备查。 你为什么使用 2 foreach ?相反,你可以做一次【参考方案2】:您可以将 EntityState 保存到 Entity 键值对并在第一次更改后使用它。
var 条目 = this.ChangeTracker.Entries() .Where(e => e.State == EntityState.Added || e.State == EntityState.Modified || e.State == EntityState.Deleted) .Select(e => new e.State, e ).ToList();
【讨论】:
请更正您的回复Editing Help 的格式,并确保您的问题回答了原作者的问题。 请阅读How to answer 并更新您的答案。以上是关于如何从实体框架 6 中的 Auditlog 实体获取 id的主要内容,如果未能解决你的问题,请参考以下文章