简体   繁体   English

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

[英]Implementing object change tracking in an N-Tier WCF MVC application

Most of the examples I've seen online shows object change tracking in a WinForms/WPF context. 我在网上看到的大多数示例都显示了WinForms / WPF上下文中的对象更改跟踪。 Or if it's on the web, connected objects are used, therefore, the changes made to each object can be tracked. 或者,如果它在Web上,则使用连接对象,因此,可以跟踪对每个对象所做的更改。

In my scenario, the objects are disconnected once they leave the data layer (Mapped into business objects in WCF, and mapped into DTO on the MVC application) 在我的场景中,对象一旦离开数据层就会断开连接(映射到WCF中的业务对象,并映射到MVC应用程序上的DTO)

When the users make changes to the object on MVC (eg, changing 1 field property), how do I send that change from the View, all the way down to the DB? 当用户对MVC上的对象进行更改(例如,更改1字段属性)时,如何从View中将该更改一直发送到DB?

I would like to have an audit table, that saves the changes made to a particular object. 我想有一个审计表,它保存对特定对象所做的更改。 What I would like to save is the before & after values of an object only for the properties that we modified 我想要保存的是仅对我们修改的属性的对象的前后值

I can think of a few ways to do this 我可以想到几种方法来做到这一点

1) Implement an IsDirty flag for each property for all Models in the MVC layer(or in the javascript?). 1)为MVC层(或javascript中的)中的所有模型的每个属性实现一个IsDirty标志。 Propagate that information all the way back down to the service layer, and finally the data layer. 将该信息一直传播回服务层,最后传播到数据层。

2) Having this change tracking mechanism within the service layer would be great, but how would I then keep track of the "original" values after the modified values have been passed back from MVC? 2)在服务层中使用这种更改跟踪机制会很好,但是如何在从MVC传回修改后的值之后跟踪“原始”值?

3) Database triggers? 3)数据库触发器? But I'm not sure how to get started. 但我不知道如何开始。 Is this even possible? 这甚至可能吗?

Are there any known object change tracking implementations out there for an n-tier mvc-wcf solution? 对于n层mvc-wcf解决方案,是否有任何已知的对象更改跟踪实现?

Example of the audit table: 审计表的示例:

Audit table

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

Possible solutions to this problem will depend in large part on what changes you allow in the database while the user is editing the data. 此问题的可能解决方案在很大程度上取决于用户编辑数据时您在数据库中允许的更改。

In otherwords, once it "leaves" the database, is it locked exclusively for the user or can other users or processes update it in the meantime? 换句话说,一旦它“离开”数据库,它是专门为用户锁定还是其他用户或进程可以在此期间更新它?

For example, if the user can get the data and sit on it for a couple of hours or days, but the database continues to allow updates to the data, then you really want to track the changes the user has made to the version currently in the database, not the changes that the user made to the data they are viewing. 例如,如果用户可以获取数据并坐在上面几个小时或几天,但数据库继续允许更新数据,那么您真的想要跟踪用户对当前版本所做的更改。数据库,而不是用户对他们正在查看的数据所做的更改。

The way that we handle this scenario is to start a transaction, read the entire existing object, and then use reflection to compare the old and new values, logging the changes into an audit log. 我们处理此方案的方式是启动事务,读取整个现有对象,然后使用反射来比较旧值和新值,将更改记录到审计日志中。 This gets a little complex when dealing with nested records, but is well worth the time spent to implement. 在处理嵌套记录时,这会有点复杂,但非常值得花时间来实现。

If, on the other hand, no other users or processes are allowed to alter the data, then you have a couple of different options that vary in complexity, data storage, and impact to existing data structures. 另一方面,如果不允许其他用户或进程更改数据,那么您有几个不同的选项,其复杂性,数据存储和对现有数据结构的影响各不相同。

For example, you could modify each property in each of your classes to record when it has changed and keep a running tally of these changes in the class (obviously a base class implementation helps substantially here). 例如,您可以修改每个类中的每个属性以记录它何时发生更改,并在类中保持这些更改的运行记录(显然,基类实现在这里有很大帮助)。

However, depending on the point at which you capture the user's changes (every time they update the field in the form, for example), this could generate a substantial amount of non-useful log information because you probably only want to know what changed from the database perspective, not from the UI perspective. 但是,根据捕获用户更改的位置(例如,每次更新表单中的字段),这可能会生成大量无用的日志信息,因为您可能只想知道更改的内容数据库透视图,而不是UI透视图。

You could also deep clone the object and pass that around the layers. 您还可以深度克隆对象并在图层周围传递它。 Then, when it is time to determine what has changed, you can again use reflection. 然后,当确定已更改的内容时,您可以再次使用反射。 However, depending on the size of your business objects, this approach can impose a hefty performance penalty since a complete copy has to be moved over the wire and retained with the original record. 但是,根据业务对象的大小,这种方法可能会造成严重的性能损失,因为必须通过线路移动完整的副本并保留原始记录。

You could also implement the same approach as the "updates allowed while editing" approach. 您还可以实现与“编辑时允许的更新”方法相同的方法。 This, in my mind, is the cleanest solution because the original data doesn't have to travel with the edited data, there is no possibility of tampering with the original data and it supports numerous clients without having to support the change tracking in the UI level. 在我看来,这是最干净的解决方案,因为原始数据不必随编辑数据一起传输,不可能篡改原始数据并且它支持众多客户端而无需支持UI中的更改跟踪水平。

There are two parts to your question: 您的问题分为两部分:

  1. How to do it in MVC: 如何在MVC中做到这一点:

The usual way: you send the changes back to the server, a controller handles them, etc. etc.. The is nothing unusual in your use case that mandates a change in the way MVC usually works. 通常的方法是:您将更改发送回服务器,控制器处理它们等等。在您的用例中强制要求改变MVC通常的工作方式并不罕见。 It is better for your use case scenario for the changes to be encoded as individual change operations, not as a modified object were you need to use reflection to find out what changes if any the user made. 对于您的用例场景,最好将更改编码为单独的更改操作,而不是作为修改的对象,您需要使用反射来找出用户所做的更改。

  1. How to do it on the database: This is probably your intended question: 如何在数据库上执行此操作:这可能是您想要的问题:

First of all stay away from ORM frameworks, life is too complex as it. 首先要远离ORM框架,生活太复杂了。

On the last step of the save operation you should have the following information: 在保存操作的最后一步,您应该具有以下信息:

  • The objects and fields that need to change and their new values. 需要更改的对象和字段及其新值。

You need to keep track of the following information: 您需要跟踪以下信息:

  • What the last change to the object you intend to modify in the database. 您要在数据库中修改的对象的最后一次更改。

This can be obtained from the Audit table and needs to be saved in a Session (or Session like object). 这可以从Audit表中获取,并且需要保存在Session(或Session like对象)中。

Then you need to do the following in a transaction: 然后,您需要在事务中执行以下操作:

  • Obtain the last change to the object(s) being modified from the database. 从数据库中获取要修改的对象的最后一次更改。
  • If the objects have changed abort, and inform the user of the collision. 如果对象已更改中止,则通知用户发生冲突。
  • If not obtain the current values of the fields being changed. 如果未获取要更改的字段的当前值。
  • Save the new values. 保存新值。
  • Update the Audit table. 更新Audit表。

I would use a stored procedure for this to make the process less chatty, and for greater separations of concerns between the database code and the application code. 我会使用一个存储过程来使这个过程不那么繁琐,并且可以更好地分离数据库代码和应用程​​序代码之间的关注点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM