使用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中的触发器,但是很难在对象模型中始终发生变化来维护它们。