我正在为我的MVC应用程序建立一个变更历史/审计日志,该应用程序使用Entity Framework。
具体地,在编辑方法public ActionResult Edit(ViewModel vm)
中,我们找到要更新的对象,然后使用TryUpdateModel(object)
将表单上的值转换到要更新的对象上。
当该对象的任何字段更改时,我想记录更改历史。所以基本上我需要在编辑之前复制该对象,然后在TryUpdateModel(object)
完成工作后进行比较。即:
[HttpPost]
public ActionResult Edit(ViewModel vm)
{
//Need to take the copy here
var object = EntityFramework.Object.Single(x=>x.ID = vm.ID);
if (ModelState.IsValid)
{
//Form the un edited view model
var uneditedVM = BuildViewModel(vm.ID); //this line seems to confuse the EntityFramework (BuildViewModel() is used to build the model when originally displaying the form)
//Compare with old view model
WriteChanges(uneditedVM, vm);
...
TryUpdateModel(object);
}
...
}
问题在于当代码获取“未编辑的vm”时,会导致实体框架出现一些意外的更改,从而使TryUpdateModel(object);
抛出UpdateException
异常。
因此问题是 - 在这种情况下 - 我该如何在不影响或更改实体框架的情况下创建一个object
的副本以用于比较/审计历史记录?
编辑:不想使用触发器。需要记录执行操作的用户名。
编辑1:使用EFv4,不太确定如何覆盖SaveChanges()
,但这可能是一种选项。
对于这样一个简单的需求,这条路似乎没有任何进展!最终我成功地进行了正确的覆盖,但是现在我用那段代码却得到了一个异常:
public partial class Entities
{
public override int SaveChanges(SaveOptions options)
{
DetectChanges();
var modifiedEntities = ObjectStateManager.GetObjectStateEntries(EntityState.Modified);
foreach (var entry in modifiedEntities)
{
var modifiedProps = ObjectStateManager.GetObjectStateEntry(entry).GetModifiedProperties(); //This line throws exception The ObjectStateManager does not contain an ObjectStateEntry with a reference to an object of type 'System.Data.Objects.EntityEntry'.
var currentValues = ObjectStateManager.GetObjectStateEntry(entry).CurrentValues;
foreach (var propName in modifiedProps)
{
var newValue = currentValues[propName];
//log changes
}
}
//return base.SaveChanges();
return base.SaveChanges(options);
}
}