我想在我的项目中维护所有修改的记录和删除的记录,并使用状态列跟踪它们的状态。下面是我第一次尝试的代码,但由于显而易见的原因,我似乎无法将 OriginalValues.ToObject()
转换为 DbEntityEntry。我应该如何着手完成这项工作?
public override int SaveChanges()
{
var now = DateTime.Now;
var currentUser = HttpContext.Current.User.Identity.Name;
var trackedEntities = ChangeTracker.Entries<ITrackable>();
foreach (var trackedEntity in trackedEntities)
{
switch(trackedEntity.State)
{
case System.Data.EntityState.Added:
trackedEntity.Entity.CreatedDate = now;
trackedEntity.Entity.CreatedBy = currentUser;
trackedEntity.Entity.Status = Status.Active;
break;
case System.Data.EntityState.Modified:
var originalEntity = trackedEntity.OriginalValues.ToObject() as DbEntityEntry<ITrackable>;
originalEntity.Entity.ModifiedDate = now;
originalEntity.Entity.ModifiedBy = currentUser;
originalEntity.Entity.Status = Status.Modified;
var newEntity = trackedEntity.CurrentValues.ToObject() as DbEntityEntry<ITrackable>;
newEntity.State = System.Data.EntityState.Added;
newEntity.Entity.Status = Status.Active;
break;
case System.Data.EntityState.Deleted:
trackedEntity.State = System.Data.EntityState.Modified;
trackedEntity.Entity.Status = Status.Deleted;
break;
}
}
return base.SaveChanges();
}
最佳答案
我不确定我是否正确理解了您在 Modified
中想要实现的目标案件。但我的理解是 ToObject()
创建一个全新的对象并用 OriginalValues
中的属性值填充它字典。所以,originalEntity
不附加到上下文,当变量超出范围时将被垃圾收集而不会产生任何影响。
因此,您不需要保存 originalEntity
吗?作为一个新添加的实体到数据库来保存修改保存前的最后一个版本?
我会试试这个:
case System.Data.EntityState.Modified:
var originalEntity = trackedEntity.OriginalValues.ToObject() as ITrackable;
originalEntity.ModifiedDate = now;
originalEntity.ModifiedBy = currentUser;
originalEntity.Status = Status.Modified;
Entry(originalEntity).Status = System.Data.EntityState.Added;
trackedEntity.Entity.Status = Status.Active;
break;
trackedEntity
无论如何都会被保存,因为它处于状态 Modified
和 originalEntity
将被创建并保存为一个新对象,代表修改前的状态。
我希望转换为 ITrackable
应该可以,因为 ToObject()
创建一个由 OriginalValues
表示的类型的对象字典,那必须是 ITrackable
因为你过滤了 ChangeTracker.Entries
通过此接口(interface)进行枚举。
以上内容未经测试,我不确定它是否有效。
编辑
上面的命名有点困惑,因为originalEntity
是您模型中的一个实体,而 trackedEntity
是 DbEntityEntry<T>
.也许将其重命名为 originalEntityObject
(丑)或更好trackedEntityEntry
.
只需提及:调用 ChangeTracker.DetectChanges()
是绝对必要的(除非您因此使用更改跟踪代理)在您输入 foreach
之前循环,否则条目可能不处于正确的最终状态并且您输入错误 case
部分或根本没有部分(当状态为 Unchanged
但属性仍已更改时)。通过与 OriginalValues
中的快照进行比较来检测 POCO 更改最后的比较是在 base.SaveChanges
中完成的这是在你的循环之后,为时已晚。 (另请参阅此处答案中的“编辑 2”:https://stackoverflow.com/a/6157071/270591。)
关于c# - 我应该如何覆盖 DbContext 上的 SaveChanges() 方法,以便使用 EF 4.3 维护已删除/修改的记录?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10502325/