【问题标题】:How to implement a MVC 4 change log?如何实现 MVC 4 更改日志?
【发布时间】:2013-10-06 23:12:00
【问题描述】:

我目前正在开发一个 mvc 4 应用程序。 客户希望有一个更改日志,以便他们可以查看哪些字段已更改。在编辑的情况下,它应该显示旧值和新值。如果是删除,那么它应该显示删除了哪一行。

实现这样的目标的最佳方法是什么?

澄清一下..更改将是数据库中的实际数据..

即我可能有客户姓名和地址的记录..用户可能会更新地址..我需要能够查看用户更改的内容..旧数据和新数据

谢谢...

【问题讨论】:

  • 到底发生了什么变化?编码?数据来源?用户界面?您可以在文档中边写边改吗?

标签: .net asp.net-mvc-3 c#-4.0 asp.net-mvc-4


【解决方案1】:

如果您想获取数据库中现有模型与修改时提交的模型之间发生更改的字段列表,则可以在控制器的 Edit Post 方法中执行此操作:

IEnumerable<string> changedFields = Audit.GetPropertyDifferences(existingModel, newModel);

我创建了一个简单的函数,它返回一堆显示更改的属性的字符串:

public static class Audit
{
    public static IEnumerable<string> GetPropertyDifferences<T>(this T obj1, T obj2)
    {
        PropertyInfo[] properties = typeof(T).GetProperties();
        List<string> changes = new List<string>();
        string name = string.Empty;

        foreach (PropertyInfo pi in properties)
        {
            object value1 = typeof(T).GetProperty(pi.Name).GetValue(obj1, null);
            object value2 = typeof(T).GetProperty(pi.Name).GetValue(obj2, null);
            DisplayNameAttribute attr = (DisplayNameAttribute)pi.GetCustomAttribute(typeof(DisplayNameAttribute));

            if (value1 != value2)
            {
                if (attr == null)
                {
                    name = pi.Name;
                }
                else
                {
                    name = attr.DisplayName;
                }
                if (value1 == null)
                {
                    changes.Add(string.Format("<li>{1} was added to {0}</li>", name, value2));
                }
                else if (value2 == null)
                {
                    changes.Add(string.Format("<li>{1} was removed from {0}</li>", name, value1));
                }
                else
                {
                    changes.Add(string.Format("<li>{0} changed from {1} to {2}</li>", name, value1, value2));
                }
            }
        }
        return changes;
    }

}

此代码检查是否在模型中设置了 DisplayName 属性,如果存在,则使用该属性代替属性名称。

然后您可以显示这些更改或将它们保存到数据库中,如下所示:

if (changedFields.Count() != 0)
{
    foreach (string i in changedFields)
    {
        // Do something
    }
}

【讨论】:

  • 这意味着你必须把这段代码放在你修改数据的任何地方。这是一个巨大的维护噩梦。最重要的是,它忽略了数据可能从其他来源发生变化,例如从数据导入,甚至是由于其他一些过程的结果。现在,如果你也有这些地方,你必须将代码添加到这些地方。在数据库中的数据发生变化的时候这样做更容易维护。
  • 当然 - 您发布了 OP 未接受的数据库解决方案,这就是我发布替代选项的原因。 GetPropertyDifferences 函数只需要编写一次,然后您要审计的关键表上的每个控制器只需要少量代码。然后,您可以使用 TempData 在提交时轻松显示更改字段的通知。
【解决方案2】:

这通常使用数据库中的触发器来完成。您创建一个审计表,然后创建捕获每个更改并记录它们的触发器。

这里有一篇讨论这个的文章:

http://www.codeproject.com/Articles/441498/Quick-SQL-Server-Auditing-Setup

较新版本的 SQL Server 内置了审核功能,但仅限于非常昂贵的企业版。大多数人无法使用这些功能。

另一种选择,我无法评价它的效果如何,它是声称增加审计功能的第三方工具。例如,一个简单的谷歌搜索发现了这些:

http://krell-software.com/omniaudit/

https://renholdsoftware.com/SQLTableAudit

【讨论】:

  • @TimMedora - 正如我所说,SQL Server 的最新版本可以做到这一点,但它需要企业版。即使在 SQL 2012 中也是如此,至少如果您想捕获哪些数据发生了变化。
  • 我在和某人交谈,他们说我应该使用实体框架来做更改日志,因为这不依赖于实际的数据库。(即 sqlserver).. 是否有任何有效性那个?
  • @user2206329 - 也许吧。问题是使用软件解决方案不会捕获手动对数据库所做的更改(由具有 SSMS 的用户或其他可能更改数据库的工具)。另一个问题是,如果您的本地记录缓存变得太大,软件审核可能会导致性能问题,因为您现在必须扫描整个缓存以查找更改。您的客户是否可能改变数据库技术?出于性能、稳健性和安全性原因,通常首选数据库级审计。
  • @Mystere Man - 客户不会(到目前为止),但我只是想知道利弊,你已经解释得很好。因此,使用桌子上的触发器。这意味着对于每个表,我将需要 3 个触发器,如果​​我有 10 个表,则需要 30 个触发器等......
  • @user2206329 - 通常只在关键表上设置审计就足够了。如果他们想在所有事情上都使用它,那么他们必须了解其后果。
猜你喜欢
  • 2010-12-28
  • 2012-03-28
  • 2013-04-15
  • 2012-02-17
  • 1970-01-01
  • 2018-12-24
  • 1970-01-01
  • 2013-06-03
  • 2020-03-30
相关资源
最近更新 更多