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

本文关键字:检测 外部 哈希 实体 框架 -通 | 更新日期: 2023-09-27 18:28:19

我正在用实体框架作为数据存储来编程一个WPF C#应用程序。数据库对外部更改是开放的,即用户可以登录到我的应用程序之外的数据库并编辑,例如,特定实体的名称。我希望保留此功能,因为它允许用户轻松地从不同来源导入数据。但是,如果对特定实体进行了这样的更改,我想通知用户。

为了实现这一点,我实施了哈希策略。每次保存时,应用程序都会为实体计算一个MD5哈希。加载时,它将根据此哈希验证实体,以确保没有进行任何外部更改。我正在使用以下示例实现哈希策略,该示例使用BinaryFormatter类:http://www.codeproject.com/Articles/21312/Generating-MD-Hash-out-of-C-Objects

然而,我所经历的是,实体不会返回相同的散列(即使没有外部更改)。这是因为"_entitywrapper"属性也被序列化了吗?其中,EF在跟踪实体时会自动向每个实体添加"_entity Wrapper"?

如果真的是这样的话,我应该使用一种不同的序列化方法,或者一种完全不同的方法吗?

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

当然,BinaryFormatter不是最好的方法。无论是从性能角度还是从可用性角度。

如果您想要一个快速、易于编写的二进制序列化程序,您应该使用协议缓冲区。C#有两种实现。

  • Protobuf net
  • 协议缓冲区csharp端口

你可以在Nuget上找到它们。

但是,如果您打开以更改方法,为什么不使用设置为上次修改的时间戳或版本id?

  • hash方法的优点是,它允许将任何回滚到原始值的行为视为"无更改"事件
  • 然而,时间戳实现起来要简单得多,并且在cpu处理中成本更低(无序列化,无散列)
  • 版本id在cpu处理方面甚至更高效,但它包含的信息更少

时间戳方法:

  • 在实体中添加一个Datetime字段,每次修改时都设置为Datetime.UtcNow。如果一个对象的时间戳比上次加载的时间戳更新,那么它同时也被修改了。注意:它与并发中使用的时间戳无关

优点:-易于理解并向同事解释
缺点:-需要在每个实体中实施。需要在表中添加一列。如果经常调用Datetime.UtcNow,那么它的cpu成本可能会很高。

版本id方法:

  • 在实体中添加一个、intlong字段,每次修改实体时增加该字段。如果一个对象的版本id大于它的上一个版本id,那么它同时也被修改了

它与时间戳方法没有太大区别,但它更具cpu效率,使用更少的数据库内存。