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