在N层WCF MVC应用程序中实现对象更改跟踪

时间:2013-07-22 02:57:26

标签: c# asp.net-mvc inotifypropertychanged n-tier-architecture change-tracking

我在网上看到的大多数示例都显示了WinForms / WPF上下文中的对象更改跟踪。或者,如果它在网络上,则使用连接的对象,因此,可以跟踪对每个对象所做的更改。

在我的场景中,一旦对象离开数据层(映射到WCF中的业务对象,并映射到MVC应用程序上的DTO),对象就会断开连接。

当用户对MVC上的对象进行更改(例如,更改1字段属性)时,如何从View中将该更改一直发送到DB?

我想要一个审计表,它保存对特定对象所做的更改。我想要保存的是之前&仅在我们修改的属性的对象值之后

我可以想到几种方法来做到这一点

1)为MVC层(或javascript中的)中的所有模型的每个属性实现一个IsDirty标志。将该信息一直传播回服务层,最后传播到数据层。

2)在服务层中使用这种更改跟踪机制会很棒,但是如何在从MVC传回修改后的值之后跟踪“原始”值?

3)数据库触发器?但我不知道如何开始。这甚至可能吗?

对于n层mvc-wcf解决方案,是否有任何已知的对象更改跟踪实现?

审计表的示例:

Audit table

Id              Object         Property         OldValue                NewValue
--------------------------------------------------------------------------------------
1               Customer       Name             Bob                     Joe
2               Customer       Age              21                      22

2 个答案:

答案 0 :(得分:3)

此问题的可能解决方案在很大程度上取决于用户编辑数据时您在数据库中允许的更改。

换句话说,一旦它“离开”数据库,它是专门为用户锁定还是其他用户或进程可以在此期间更新它?

例如,如果用户可以获取数据并坐在上面几个小时或几天,但数据库继续允许更新数据,那么您真的想要跟踪用户对数据所做的更改。当前在数据库中的版本,而不是用户对他们正在查看的数据所做的更改。

我们处理此方案的方式是启动事务,读取整个现有对象,然后使用反射来比较旧值和新值,将更改记录到审核日志中。在处理嵌套记录时,这会有点复杂,但非常值得花时间来实现。

另一方面,如果不允许其他用户或进程更改数据,那么您有几个不同的选项,其复杂性,数据存储和对现有数据结构的影响各不相同。

例如,您可以修改每个类中的每个属性以记录它何时发生更改并在类中保持这些更改的运行记录(显然基类实现在这里有很大帮助)。

但是,根据您捕获用户更改的时间点(例如,每次更新表单中的字段),这可能会生成大量无用的日志信息,因为您可能只想知道从数据库角度改变了什么,而不是从UI角度来看。

您还可以深度克隆对象并将其传递到图层周围。然后,当确定已更改的内容时,您可以再次使用反射。但是,根据业务对象的大小,这种方法可能会造成严重的性能损失,因为必须通过线路移动完整的副本并保留原始记录。

您还可以实现与“编辑时允许的更新”方法相同的方法。在我看来,这是最干净的解决方案,因为原始数据不必随编辑数据一起传输,不可能篡改原始数据并且它支持众多客户端而无需支持UI中的更改跟踪水平。

答案 1 :(得分:0)

您的问题分为两部分:

  1. 如何在MVC中执行此操作:
  2. 通常的方法:将更改发送回服务器,控制器处理它们等等。 在您的用例中强制要求改变MVC通常的工作方式并不罕见。 对于您的用例场景,最好将更改编码为单独的更改操作,而不是作为修改的对象,您需要使用反射来找出用户所做的更改。

    1. 如何在数据库上执行此操作: 这可能是您想要的问题:
    2. 首先远离ORM框架,生活太复杂了。

      在保存操作的最后一步,您应该具有以下信息:

      • 需要更改的对象和字段及其新值。

      您需要跟踪以下信息:

      • 您要在数据库中修改的对象的最后一次更改。

      这可以从Audit表中获取,需要保存在Session(或类似Session的对象)中。

      然后您需要在事务中执行以下操作:

      • 从数据库中获取对要修改的对象的最后一次更改。
      • 如果对象已更改中止,并通知用户发生冲突。
      • 如果没有获取要更改的字段的当前值。
      • 保存新值。
      • 更新审核表。

      我会使用一个存储过程来减少这个过程,并使数据库代码和应用程​​序代码之间的关注点更加分离。