我有一个实体类,它有一个整数属性(名为ROW_VERSION),ConcurrencyMode设置为“Fixed”,用于乐观并发检查。在保存此类型的实体之前,我在应用程序代码中增加此列的值(因此StoreGeneratedPattern设置为None)。这在保存更改时效果很好。
现在,当我有一个先前加载的实体(使用ROW_VERSION = x)并且我创建一个新的DbContext时,我还想检测并发错误,附加此实体并发出涉及该实体的查询。问题在于,如果ROW_VERSION由另一个客户端应用程序(ROW_VERSION = x + 1)递增,则在我的查询期间不会检测到这一点,因为附加实体的值具有明显优先级(这对于常见列值完全有意义) )。
另一方面,对于我的并发检查列,如果EF使用当前数据库值更新值,那将是很好的,因此我可以将其与期望值进行比较。或者,从查询执行中抛出的异常也是可以接受的。
我正在使用.NET 4.0的实体框架。
编辑(回应Gert Arnold的评论):
我试着再澄清一下我的问题......
我的申请一般如何运作的说明:
有一个树视图显示我的可用实体对象,在选择一个实体对象时,从DB加载完整实体以显示在详细视图中,可在其中进行编辑
对实体对象的修改不会立即保存,而是缓存在内存中,因此当用户点击保存按钮时,不同实体对象的修改会堆积起来并一起保存。
DbContexts是为查询和保存更改单独创建的(即我没有始终使用相同的DbContext,但它们会根据需要进行实例化。)
当加载实体对象以在详细视图中显示时,所有先前修改的实体对象(已缓存)将首先附加到用于查询的DbContext。然后发出实际查询。 因此,如果我查询实体对象,那么在我将修改后的版本作为结果而不是数据库中的版本(在此期间可能已更改)之前进行了修改。
所以这是一个显示我的问题的例子:
Client App 1加载一个ROW_VERSION = 1的实体对象,处理DbContext并保留对该实体对象的引用以供进一步编辑。
Client App 2加载步骤1中提到的同一实体对象,更改属性并保存更改。这会导致DB中的ROW_VERSION递增(现在为2)。
Client App 1的用户现在更改了实体对象的某些属性(它仍在内存中,ROW_VERSION为1)。
在客户端应用程序1保存更改之前,它会加载一些其他实体对象以供显示,并最终再次选择有问题的实体对象(例如,查看所做的更改)。这会导致查询结果将包含已更改的实体对象(因为它在将实际查询发送到数据库之前附加到DbContext)。
这是我的问题:此时实体框架可以将附加对象的ROW_VERSION与实际查询结果中的对象的ROW_VERSION进行比较,检测不匹配,例如抛出异常。
但是EF会像所有其他属性一样处理ROW_VERSION属性,而这些属性可能已被客户端更改。
所以我希望EF专门处理ROW_VERSION属性,并在每个查询上比较它的值以检测其他客户端的更改。这样,我会比等待SaveChanges调用时更早地检测到并发情况。
答案 0 :(得分:1)
我想我现在明白了,但我不知道实体框架如何在这里帮助你。
ConcurrencyMode
以这种方式实现(即使在可配置的情况下),这将偏离预期的行为。据我所知,如果你想要这个早期预警系统,你必须自己编程。这应该涉及一些查询来具体读取版本值,因为带有Refresh
(ObjectContext)或StoreWins
(DbContext)的Reload
总是会覆盖所有值。