一尘不染

使用MVC和实体框架实施审核日志/更改历史记录

c#

我正在将更改历史记录/审核日志构建到使用实体框架的MVC应用程序中。

因此,特别是在edit方法中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”时,这会导致EntityFramework中发生一些意外更改-
从而TryUpdateModel(object);引发UpdateException

因此,问题是 -在这种情况下-
我如何创建objectEntityFramework外部的副本以比较更改/审核历史记录,以便它根本不影响或更改EntityFramework

编辑:不想使用触发器。需要记录执行该操作的用户名。

edit1:使用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);
    }
}

阅读 528

收藏
2020-05-19

共1个答案

一尘不染

如果您使用的是EF 4,则可以订阅该SavingChanges活动。

由于Entities是局部类,因此可以在单独的文件中添加其他功能。因此,创建一个名为的新文件,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,则可以阅读本文以提取更改

2020-05-19