使用MVC和entity framework实施审计日志/更改历史logging

我正在修改历史/审计日志到我的MVC应用程序正在使用entity framework。

特别是在编辑方法public ActionResult Edit(ViewModel vm) ,我们find了我们正在尝试更新的对象,然后使用TryUpdateModel(object)将表单中的值转换为我们要更新的对象。

我想在该对象的任何字段更改时logging更改。 所以基本上我需要的是在编辑之前对象的一个​​副本,然后在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); } ... } 

但问题是当代码检索“未经编辑的虚拟机”,这是在EntityFramework中引起一些意想不到的变化 – 以便TryUpdateModel(object); 抛出一个UpdateException

所以问题是 – 在这种情况下 – 如何在EntityFramework之外创build一个object副本来比较更改/审计历史logging,以便根本不影响或更改EntityFramework

编辑:不想使用触发器。 需要logging用户名。

编辑1:使用EFv4,不太确定如何重写SaveChanges()但它可能是一个选项


这条路线似乎无处可去,对于这样一个简单的要求! 我终于得到它重写正确,但现在我得到一个exception与该代码:

 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); } } 

如果您使用的是EF 4,则可以订阅SavingChanges事件。

由于Entities是一个部分类,你可以添加额外的function在一个单独的文件。 因此,创build一个名为Entities的新文件,并在那里实现部分方法OnContextCreated来挂钩事件

 public partial class Entities { partial void OnContextCreated() { SavingChanges += OnSavingChanges; } void OnSavingChanges(object sender, EventArgs e) { var modifiedEntities = ObjectStateManager.GetObjectStateEntries(EntityState.Modified); foreach (var entry in modifiedEntities) { var modifiedProps = ObjectStateManager.GetObjectStateEntry(entry.EntityKey).GetModifiedProperties(); var currentValues = ObjectStateManager.GetObjectStateEntry(entry.EntityKey).CurrentValues; foreach (var propName in modifiedProps) { var newValue = currentValues[propName]; //log changes } } } } 

如果您使用的是EF 4.1,则可以阅读本文以提取更改

请参阅我为此编写的entity framework日志库FrameLog 。 它是开源的,包括用于商业用途。

我知道你只是看到一个代码片段展示了如何做到这一点,但为了正确处理所有的日志logging,包括关系变化和多对多的变化,代码变得相当大。 希望图书馆能够很好地满足你的需求,但是如果没有,你可以自由地调整代码。

FrameLog可以logging对所有标量和导航属性的更改,还可以指定一个您感兴趣的子集。

代码项目中有一篇评价很高的文章: 使用entity framework实现审计跟踪 。 它似乎做你想要的。 我已经开始在一个项目中使用这个解决scheme。 我首先在数据库中编写了T-SQL中的触发器,但是很难在对象模型中始终发生变化来维护它们。