使用 MVC & 实现审计日志/更改历史记录实体框架 [英] Implementing Audit Log / Change History with MVC & Entity Framework

查看:26
本文介绍了使用 MVC & 实现审计日志/更改历史记录实体框架的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为使用实体框架的 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆