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

时间:2015-12-28 15:21:42

标签: c# wpf entity-framework hash

我使用Entity Framework作为数据存储编程WPF C#应用程序。数据库对外部更改是开放的,即用户可以在我的应用程序之外登录数据库并编辑,例如,特定实体的名称。我希望保持此功能,因为它允许用户轻松导入来自不同来源的数据。但是,我想告知用户是否对特定实体进行了此类更改。

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

我遇到的是,实体没有返回相同的哈希值(即使没有外部更改)。这是由于" _entitywrapper"属性也被序列化,其中" _entitywrapper"在跟踪实体时,EF会自动添加到每个实体吗?

如果情况确实如此,我应该使用不同的序列化方法,还是完全不同的方法?

1 个答案:

答案 0 :(得分:1)

当然,BinaryFormatter不是最佳方式。无论是绩效观还是可用性。

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

您可以在Nuget上找到它们。

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

  • 哈希方法的优点是,它允许将任何回滚到原始值视为“无更改”事件。
  • 时间戳但实现起来要简单得多,而且cpu处理成本更低(没有序列化,没有哈希)
  • 版本ID 在cpu处理方面效率更高,但信息量更少。

时间戳方法:

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

<强>优点:   - 易于理解并向同事解释。
缺点:   - 需要在每个实体中实施。需要在表格中添加一列。如果经常调用,Datetime.UtcNow可能会很昂贵。

版本ID方法:

  • 在实体中添加{,intlong字段,每次修改实体时都会增加该字段。如果对象的版本ID大于它的上一个版本ID,则同时修改它。

它与timestamp方法没有太大区别,但它更高效,并且使用更少的数据库内存。