DbUpdateConcurrencyException 和 40001 postgres 代码有什么区别?

What's the difference between DbUpdateConcurrencyException and 40001 postgres code?

我有两笔交易。 首先,我 select 一个实体,进行验证,将客户端文件提供的上传到 S3,然后使用有关 S3 文件的信息更新该实体。 第二笔交易只是删除这个实体。 现在,假设有人调用了第一笔交易并立即调用了第二笔交易。第二个将进行得更快,第一个将抛出 DbUpdateConcurrencyException,因为 selected 实体在更新查询中不再存在。

当我的交易有 IsolationLevel.ReadCommited 时,我得到 DbUpdateConcurrencyException。但是如果我设置 IsolationLevel.Serializable 它会抛出 InvalidOperationException 和 40001 postgres 代码。有人可以解释为什么我会得到不同的错误,因为在我看来结果应该是相同的,因为这两个错误都是通过更新不存在的实体调用的?

40001 错误对应于 SQLSTATE serialization_failure(参见 table of error codes)。

当数据库引擎检测到有并发事务时,它由处于可序列化隔离级别的数据库引擎生成,如果并发事务运行 串行,则此事务可能产生了无法获得的结果。 使用IsolationLevel.ReadCommited时,不可能得到这个错误,因为选择这种隔离级别恰恰意味着客户端不想让数据库完成这些隔离检查。

另一方面,DbUpdateConcurrencyException 可能不是由数据库引擎生成的。它由 entity framework 生成。数据库本身可以通过 UPDATE 更新零行,这不是 SQL 级别的错误。

我认为如果数据库首先出错,您会遇到序列化失败,如果数据库没有出错,则会遇到 DbUpdateConcurrencyException 错误,但分层顺序中的第二层(EF)会出错。

在可序列化隔离级别,处理序列化失败的典型方法是让客户端在出现 40001 错误时重试事务。重试的事务将有一个新的数据视图,并有望通过(否则,循环重试)。

在较低的隔离级别处理并发的典型方法,例如 Read Committed 它在访问对象之前显式锁定对象以强制并发事务的序列化。