与MVC和放大器实现审计日志/更改历史记录;实体框架 [英] Implementing Audit Log / Change History with MVC & Entity Framework
问题描述
我建立了更改历史记录/审计日志到正在使用的实体框架我的MVC应用程序。
所以,特别是在编辑方法公众的ActionResult编辑(视图模型VM)
,我们发现我们正在努力更新,然后使用该对象 TryUpdateModel (对象)
来转上,我们正在努力更新对象从表单中的值。
我要记录的变化时的对象更改的任何字段。所以基本上我需要的是对象的副本是编辑,然后在 TryUpdateModel(对象)后,比较之前
已完成其工作。即。
[HttpPost]
公众的ActionResult编辑(视图模型VM)
{
//这里需要采取副本
VAR对象= EntityFramework.Object.Single(X => x.ID = vm.ID); 如果(ModelState.IsValid)
{
//形成未编辑视图模型
VAR uneditedVM = BuildViewModel(vm.ID); //这一行似乎混淆的EntityFramework(BuildViewModel()用于构建模型时最初显示的形式)
//旧视图模型比较
WriteChanges(uneditedVM,VM);
...
TryUpdateModel(对象);
}
...
}
但问题是当code检索未经编辑虚拟机,这是造成中的EntityFramework一些意想不到的变化 - 这样 TryUpdateModel(对象);
抛出一个 UpdateException
。
所以,问题是 - 在这种情况下 - 我怎么创建对象的副本
的EntityFramework之外,比较变更/审计历史,所以它不会影响或改变
在的EntityFramework所有
编辑:不要使用触发器。需要登录谁做的用户名。
EDIT1:使用EFv4,也不太清楚如何去覆盖的SaveChanges()
,但它可能是一种选择
这条路线似乎无处可去,这样一个简单的要求!我终于得到它正确地覆盖,但现在我得到与code异常:
公共部分类实体
{
公共覆盖INT的SaveChanges(SaveOptions选项)
{
DetectChanges();
VAR modifiedEntities = ObjectStateManager.GetObjectStateEntries(EntityState.Modified);
的foreach(在modifiedEntities VAR进入)
{
VAR modifiedProps = ObjectStateManager.GetObjectStateEntry(项).GetModifiedProperties(); //此行抛出异常的ObjectStateManager不包含ObjectStateEntry一起类型的对象System.Data.Objects.EntityEntry的参考。
VAR currentValues = ObjectStateManager.GetObjectStateEntry(入门).CurrentValues;
的foreach(在modifiedProps VAR作为propName)
{
VAR为newValue = currentValues [作为propName]
//记录更改
}
} //返回base.SaveChanges();
返回base.SaveChanges(选件);
}
}
如果您使用的是EF 4,您可以订阅 SavingChanges
事件。
由于实体
是一个局部类你可以在一个单独的文件添加额外的功能。因此,创建一个名为实体
一个新的文件,并没有实施 OnContextCreated
部分的方法挂钩事件
公共部分类实体
{
部分无效OnContextCreated()
{
SavingChanges + = OnSavingChanges;
} 无效OnSavingChanges(对象发件人,EventArgs的发送)
{ VAR modifiedEntities = ObjectStateManager.GetObjectStateEntries(EntityState.Modified);
的foreach(在modifiedEntities VAR进入)
{
变种modifiedProps = ObjectStateManager.GetObjectStateEntry(entry.EntityKey).GetModifiedProperties();
VAR currentValues = ObjectStateManager.GetObjectStateEntry(entry.EntityKey).CurrentValues;
的foreach(在modifiedProps VAR作为propName)
{
VAR为newValue = currentValues [作为propName]
//记录更改
}
}
}
}
如果您使用的是EF 4.1你可以通过<一个href=\"http://blogs.msdn.com/b/adonet/archive/2011/01/30/using-dbcontext-in-ef-feature-ctp5-part-5-working-with-property-values.aspx\">this文章提取变化
I am building in a Change History / Audit Log to my MVC app which is using the Entity Framework.
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.
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);
}
...
}
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
.
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: 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);
}
}
IF you are using EF 4 you can subscribe to the SavingChanges
event.
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
}
}
}
}
If you are using EF 4.1 you can go through this article to extract changes
这篇关于与MVC和放大器实现审计日志/更改历史记录;实体框架的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!