简体   繁体   English

C#实体框架-通过哈希检测外部更改

[英]C# Entity Framework - Detect External Changes via Hash

I'm programming a WPF C# application with Entity Framework as the data store. 我正在使用实体框架作为数据存储来编写WPF C#应用程序。 The database is open to external changes, ie a user can log in to the database outside my application and edit, say, the name of a specific entity. 该数据库可以进行外部更改,即用户可以在我的应用程序外部登录数据库并编辑特定实体的名称。 I'd like to keep this functionality in place, as it allows the user to easily import data from different sources. 我想保留此功能,因为它允许用户轻松地从不同来源导入数据。 However, I'd like to inform the user if such a change was made to a specific entity. 但是,我想通知用户是否对特定实体进行了此类更改。

To achieve this, I implemented a hashing strategy. 为了实现这一点,我实现了哈希策略。 On each save, the app will calculate a MD5 hash for the entity. 每次保存时,应用都会为该实体计算MD5哈希值。 On load, it will verify the entity against this hash to ensure that no external changes were made. 加载时,它将对照此哈希值验证实体,以确保未进行任何外部更改。 I'm implementing the hashing strategy using the following example, which makes use of the BinaryFormatter class: http://www.codeproject.com/Articles/21312/Generating-MD-Hash-out-of-C-Objects 我正在使用以下示例实现哈希策略,该示例利用BinaryFormatter类: http : //www.codeproject.com/Articles/21312/Generating-MD-Hash-out-of-C-Objects

What I'm however experiencing, is that the entity doesn't return the same hash (even with no external changes). 但是我遇到的是,该实体没有返回相同的哈希(即使没有外部更改)。 Is this due to the "_entitywrapper" property being serialized as well, where "_entitywrapper" is added automatically to each entity by EF when tracking entities? 这是由于“ _entitywrapper”属性也被序列化了吗?在跟踪实体时,EF将“ _entitywrapper”自动添加到每个实体中吗?

If this is indeed the case, is there a different serialization methodology that I should be using, or indeed a completely different approach? 如果确实如此,是否应该使用不同的序列化方法,或者是完全不同的方法?

Sure, BinaryFormatter is not the best way to go. 当然, BinaryFormatter不是最好的方法。 Neither from performance view nor from usability. 既不是从性能角度来看,也不是从可用性方面来看。

If you want a fast, easy to write, binary serializer, you should use protocol buffer . 如果您想要一个快速,易于编写的二进制序列化程序,则应使用协议缓冲区 There are two implementations for C#. C#有两种实现。

You can found them on Nuget. 您可以在Nuget上找到它们。

However, if you open to change your approach, why not using a timestamp set to last modified, or a version id ? 但是,如果您愿意改变方法, 为什么不使用设置为最后修改的时间戳或版本ID?

  • The advantage of the hash approach is that it permits to see any rollback to original values as a "no change" event. 哈希方法的优点是它允许将任何回滚到原始值视为“无更改”事件。
  • The timestamp however is much simpler to implement and less expensive in cpu processing (no serialization, no hash) 但是, 时间戳更易于实现,并且在cpu处理中更便宜(无需序列化,无需哈希)
  • The version id is even more efficient in terms of cpu processing, however it holds less information. 就CPU处理而言, 版本ID甚至更加有效,但是它包含的信息较少。

Timestamp approach: 时间戳方法:

  • Add a Datetime field in the entity, set to Datetime.UtcNow everytime it is modified. 在实体中添加一个Datetime字段,每次修改时都设置为Datetime.UtcNow If timestamp of an object is more recent than your last load of it, then it has been modified in the meanwhile. 如果某个对象的时间戳记比您上次加载的时间戳记晚,则该对象已同时被修改。 Note: It has nothing to do with the timestamp used in concurrency. 注意:与并发中使用的时间戳无关。

Pros: - Easy to understand and to explain to co-workers. 优点: -易于理解并向同事解释。
Cons: - Need to be implemented in each entity. 缺点: -需要在每个实体中实施。 Need a column added in tables. 需要在表中添加一列。 Datetime.UtcNow can be cpu-expensive if called often. 如果经常调用, Datetime.UtcNow可能会占用大量CPU资源。

Version id approach: 版本ID方法:

  • Add a, int or a long field in the entity, increase it everytime entity is modified. 在实体中添加intlong字段,每次修改实体时将其增加。 If version id of an object is greater than your last version id of it, then it has been modified in the meanwhile. 如果对象的版本ID大于您上一个对象的版本ID,则该对象已同时被修改。

It is not much different from timestamp approach, however it is more cpu-efficient and use less database memory. 它与时间戳方法没有太大区别,但是它具有更高的CPU使用效率和更少的数据库内存。

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

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