7

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

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

当用户对 MVC 上的对象进行更改(例如,更改 1 个字段属性)时,我如何将更改从视图发送到数据库?

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

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

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
4

2 回答 2

3

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

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

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

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

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

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

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

您还可以深度克隆对象并将其传递到各个层。然后,当需要确定发生了什么变化时,您可以再次使用反射。但是,根据业务对象的大小,这种方法可能会造成严重的性能损失,因为必须通过网络传输完整的副本并与原始记录一起保留。

您还可以实施与“编辑时允许更新”方法相同的方法。在我看来,这是最简洁的解决方案,因为原始数据不必与编辑后的数据一起移动,没有篡改原始数据的可能性,并且它支持众多客户端,而无需支持 UI 中的更改跟踪等级。

于 2013-07-22T03:38:42.827 回答
0

你的问题有两个部分:

  1. 如何在 MVC 中做到这一点:

通常的方式:您将更改发送回服务器,控制器处理它们等等。在您的用例中,这并没有什么不寻常的地方,它要求改变 MVC 通常的工作方式。对于您的用例场景,最好将更改编码为单独的更改操作,而不是作为修改的对象,如果您需要使用反射来找出用户进行了哪些更改。

  1. 如何在数据库上执行此操作:这可能是您的预期问题:

首先远离ORM框架,生活太复杂了。

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

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

您需要跟踪以下信息:

  • 您打算在数据库中修改的对象的最后一次更改是什么。

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

那么你需要在一个事务中做以下事情:

  • 从数据库中获取对正在修改的对象的最后更改。
  • 如果对象发生变化则中止,并通知用户发生碰撞。
  • 如果没有获取正在更改的字段的当前值。
  • 保存新值。
  • 更新审计表。

为此,我将使用存储过程来减少流程的繁琐,并更好地分离数据库代码和应用程​​序代码之间的关注点。

于 2013-07-22T04:34:01.890 回答