我想维护项目中所有已修改的记录和已删除的记录,并使用"状态"列跟踪其状态。 下面是我第一次尝试的代码,但由于显而易见的原因,我似乎无法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
将被创建并保存为表示修改前状态的新对象。
我希望 cast to ITrackable
应该工作,因为ToObject()
创建一个由OriginalValues
字典表示的对象,并且它必须是ITrackable
,因为您通过此接口过滤ChangeTracker.Entries
枚举。
以上未经测试,我不确定它是否有效。
编辑
上面的命名有点令人困惑,因为originalEntity
是模型中的实体,而trackedEntity
是DbEntityEntry<T>
。也许将其重命名为originalEntityObject
(丑陋(或更好的trackedEntityEntry
.
值得一提的是:在进入foreach
循环之前调用ChangeTracker.DetectChanges()
是绝对必要的(除非您因此使用更改跟踪代理(,否则条目可能不处于正确的最终状态,并且您输入了错误的case
节或根本没有节(当状态Unchanged
但仍更改了属性时(。POCO 更改是通过与 OriginalValues
中的快照进行比较来检测的,最后一次比较是在循环之后base.SaveChanges
完成的,为时已晚。(另请参阅此处答案中的"编辑 2":https://stackoverflow.com/a/6157071/270591。
我正在寻找如何覆盖 SaveChanges(( 以实现类似的目标
这样投射会更容易;
((ITrackable)trackedEntity.Entity).CreatedDate = now;
虽然与您使用的方法不同,但我为此使用了存储库模式。 应用程序的其余部分只是实例化存储库类,并调用Save(objToSave)
或Delete(objToDelete)
或类似内容。 现在执行过程与实际数据存储断开连接,我可以采取适当的操作:更新ModifyDate
、更改Status
等。 如果要将DataContext
暴露给应用程序的其余部分,则很难控制幕后的细节。