【发布时间】:2019-11-24 16:30:02
【问题描述】:
我有一个父实体,我需要做一个并发检查(如下注释)
[Timestamp]
public byte[] RowVersion { get; set; }
我有一堆客户端进程,它们从这个父实体访问只读值,主要是更新它的子实体。
约束
客户端不应干扰彼此的工作(例如,更新子记录不应在父实体上引发并发异常)。
我有一个服务器进程,它会 更新这个父实体,在这种情况下如果 父实体 已更改,客户端进程需要抛出。
注意:客户端的并发检查是牺牲的,服务器的工作流程是关键任务。
问题
我需要(从客户端进程)检查父实体是否已更改而不更新父实体的行版本。
在EF中对父实体进行并发检查很容易:
// Update the row version's original value
_db.Entry(dbManifest)
.Property(b => b.RowVersion)
.OriginalValue = dbManifest.RowVersion; // the row version the client originally read
// Mark the row version as modified
_db.Entry(dbManifest)
.Property(x => x.RowVersion)
.IsModified = true;
IsModified = true 是交易破坏者,因为它会强制更改行版本。或者,在上下文中说,来自客户端进程的此检查将导致 父实体 中的行版本更改,这会不必要地干扰其他 客户端进程的 工作流。 p>
解决方法:我可能会将来自客户端进程的 SaveChanges 包装在 Transaction 中,然后随后读取父实体的行版本,反过来,如果行版本发生变化,则回滚。
总结
Entity Framework 是否有一种开箱即用的方式,我可以在其中SaveChanges(在客户端进程中为子实体)还检查父实体的行版本是否已更改(不更新父实体的行版本)。
【问题讨论】:
-
是否可以使用 sqlserver rowversion 功能? docs.microsoft.com/en-us/sql/t-sql/data-types/…
-
@ilkerkaran 是的,我正在使用它,但它更多的是如何检查父表上的并发更改而不更改该表上的
rowversion,因此SaveChanges失败实体框架。 -
这个问题和你的类似吗? social.msdn.microsoft.com/Forums/en-US/….
-
修改父子的方法有很多,还是只有几个?换句话说,您的事务变通办法会导致重复代码吗?
-
我认为您的交易解决方法还不错。特别是。封装后,优点是它都在一个地方,所以很清楚会发生什么,并且不太可能有任何副作用。任何其他解决方案,例如使用 EF 的命令树拦截器,都将由分离的代码部分组成,从而很容易在频谱的任一侧破坏某些东西。 F.e.如果没有从数据库中提取父 rowid,这一切都会失败,当代码没有显示为什么/在哪里需要它们时,这很容易忘记。此外,也许更重要的是,它将您与这个版本的 EF 联系在一起。
标签: c# sql-server entity-framework entity-framework-6 database-concurrency