1

我有一个具有整数属性(名为 ROW_VERSION)的实体类,其中 ConcurrencyMode 设置为“Fixed”以进行乐观并发检查。在保存此类型的实体之前,我会在我的应用程序代码中增加此列的值(因此 StoreGeneratedPattern 设置为 None)。这在保存更改时效果很好。

现在,当我有一个先前加载的实体(使用 ROW_VERSION = x)并创建一个新的 DbContext、附加此实体并发出涉及此实体的查询时,我还想检测并发错误。那里的问题是,如果 ROW_VERSION 被另一个客户端应用程序(ROW_VERSION = x + 1)增加,这在我的查询过程中没有被检测到,因为附加实体的值显然具有优先级(这对于常见的列值完全有意义)。

另一方面,对于我的并发检查列,如果 EF 使用当前数据库值更新该值,那就太好了,这样我就可以将它与预期值进行比较。或者,从查询执行中抛出的异常是可以接受的。

我将实体框架 4.3 与 .NET 4.0 一起使用。

编辑(回应 Gert Arnold 的评论):

我试图进一步澄清我的问题......

我的应用程序一般如何工作的注意事项:

  • 有一个树视图显示我可用的实体对象,在选择一个时,从数据库加载完整实体以显示在详细视图中,可以在其中进行编辑

  • 对实体对象的修改不会立即保存,而是缓存在内存中,因此当用户点击保存按钮时,不同实体对象的修改会堆积起来并一起保存。

  • DbContext 是单独创建的,用于查询和保存更改(即,我并不总是拥有相同的 DbContext,但它们会根据需要进行实例化)。

  • 当加载实体对象以在详细视图中显示时,所有先前修改的实体对象(被缓存)都附加到首先用于查询的 DbContext。然后发出实际的查询。因此,如果我查询一个实体对象,该对象在我将获得修改后的版本作为结果之前已被修改,而不是来自数据库的版本(同时可能已更改)。

所以这是一个显示我的问题的例子:

  1. 客户端应用程序 1 加载 ROW_VERSION = 1 的实体对象,释放 DbContext 并保留对该实体对象的引用以供进一步编辑。

  2. 客户端应用程序 2 加载步骤 1 中提到的相同实体对象,更改属性并保存更改。这会导致数据库中的 ROW_VERSION 递增(现在为 2)。

  3. Client App 1 的用户现在更改了实体对象的一些属性(它仍在内存中,ROW_VERSION 为 1)。

  4. 在客户端应用程序 1 保存更改之前,它会加载一些其他实体对象以进行显示,并最终再次选择有问题的实体对象(例如,查看所做的更改)。这会导致查询结果将包含已更改的实体对象(因为它在实际查询发送到数据库之前附加到 DbContext)。

    这是我的问题:此时实体框架可以将附加对象的 ROW_VERSION 与实际查询结果中的对象的 ROW_VERSION 进行比较,检测不匹配并例如抛出异常。

    但相反,EF 将 ROW_VERSION 属性视为可能刚刚被客户端更改的所有其他属性。

所以我希望 EF 特别对待 ROW_VERSION 属性并在每个查询中比较它的值以检测其他客户端的更改。这样,我会在等待 SaveChanges 调用之前检测到并发情况。

4

1 回答 1

1

我想我现在明白了,但我看不出 Entity Framework 如何在这里为您提供帮助。

  1. 每个定义的乐观并发是一种在提交数据时处理冲突的策略。不是在读取数据时。ConcurrencyMode因此,如果以这种方式实现(即使是可配置的),也将背离预期的行为。
  2. 假设 EF 实体类可以配置为在读取时表现得像这样。在检索这些实体的列表或包含这些实体的对象图时,很难处理所有可能的异常。是否应该回滚整个读取?所以它可能只在读取单个实体对象时才有用。那将是一个非常(阅读:也是)细粒度的配置规范。

据我所知,如果你想要这个预警系统,你必须自己编程。这应该涉及一些查询来专门读取版本值,因为Refresh使用StoreWins(ObjectContext) 或Reload(DbContext) 总是会覆盖所有值。

于 2012-11-03T17:43:36.247 回答