使用 MVC & 实现审计日志/更改历史记录实体框架 [英] Implementing Audit Log / Change History with MVC & Entity Framework
问题描述
我正在为使用实体框架的 MVC 应用程序构建更改历史记录/审核日志.
I am building in a Change History / Audit Log to my MVC app which is using the Entity Framework.
所以具体在编辑方法public ActionResult Edit(ViewModel vm)
中,找到我们想要更新的对象,然后使用TryUpdateModel(object)
进行转置从表单到我们尝试更新的对象的值.
So specifically in the edit method public ActionResult Edit(ViewModel vm)
, we find the object we are trying to update, and then use TryUpdateModel(object)
to transpose the values from the form on to the object that we are trying to update.
我想在该对象的任何字段更改时记录更改.所以基本上我需要的是在编辑之前对象的副本,然后在 TryUpdateModel(object)
完成其工作后进行比较.即
I want to log a change when any field of that object changes. So basically what I need is a copy of the object before it is edited and then compare it after the TryUpdateModel(object)
has done its work. i.e.
[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
.
But the problem is when the code retrieves the "unedited vm", this is causing some unexpected changes in the EntityFramework - so that TryUpdateModel(object);
throws an UpdateException
.
所以问题是 - 在这种情况下 - 我如何在 EntityFramework 之外创建 object
的副本来比较更改/审计历史,以便它不影响或改变EntityFramework 完全
So the question is - in this situation - how do I create a copy of the object
outside of EntityFramework to compare for change/audit history, so that it does not affect or change the
EntityFramework at all
不想使用触发器.需要记录执行此操作的用户名.
edit: Do not want to use triggers. Need to log the username who did it.
edit1:使用 EFv4,不太确定如何覆盖 SaveChanges()
但它可能是一个选项
edit1: Using EFv4, not too sure how to go about overriding SaveChanges()
but it may be an option
对于这么简单的要求,这条路线似乎无处可去!我终于让它正确覆盖了,但现在我得到了该代码的异常:
This route seems to be going nowhere, for such a simple requirement! I finally got it to override properly, but now I get an exception with that code:
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
事件.
IF you are using EF 4 you can subscribe to the SavingChanges
event.
由于 Entities
是一个分部类,您可以在单独的文件中添加其他功能.因此,创建一个名为 Entities
的新文件,并在那里实现局部方法 OnContextCreated
以连接事件
Since Entities
is a partial class you can add additional functionality in a separate file. So create a new file named Entities
and there implement the partial method OnContextCreated
to hook up the event
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,您可以通过 这篇文章 提取更改
If you are using EF 4.1 you can go through this article to extract changes
这篇关于使用 MVC & 实现审计日志/更改历史记录实体框架的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!