我有一个具有整数属性(名为 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 加载 ROW_VERSION = 1 的实体对象,释放 DbContext 并保留对该实体对象的引用以供进一步编辑。
客户端应用程序 2 加载步骤 1 中提到的相同实体对象,更改属性并保存更改。这会导致数据库中的 ROW_VERSION 递增(现在为 2)。
Client App 1 的用户现在更改了实体对象的一些属性(它仍在内存中,ROW_VERSION 为 1)。
在客户端应用程序 1 保存更改之前,它会加载一些其他实体对象以进行显示,并最终再次选择有问题的实体对象(例如,查看所做的更改)。这会导致查询结果将包含已更改的实体对象(因为它在实际查询发送到数据库之前附加到 DbContext)。
这是我的问题:此时实体框架可以将附加对象的 ROW_VERSION 与实际查询结果中的对象的 ROW_VERSION 进行比较,检测不匹配并例如抛出异常。
但相反,EF 将 ROW_VERSION 属性视为可能刚刚被客户端更改的所有其他属性。
所以我希望 EF 特别对待 ROW_VERSION 属性并在每个查询中比较它的值以检测其他客户端的更改。这样,我会在等待 SaveChanges 调用之前检测到并发情况。