如何处理聚合根之间引用的并发性?

How do I deal with concurrency regarding references between aggregate roots?

我有一个聚合根 (Slave),它引用了另一个 AG (Master),也就是说我在数据库中有一个外键约束。

不太可能,但仍有可能在插入引用 Slave 之前删除引用的 Master。这可以避免使用 repeatable readserializable 事务隔离级别,但它会对性能产生负面影响。

在这种情况下,我更喜欢乐观并发检查:尝试并可能失败。但是,很难将抛出的 DbUpdateEception 追溯到问题的语义。

换句话说,有文本消息对于理解哪个引用实际上失败不是很方便:

An error occurred while updating the entries. See the inner exception for details.

Inner exception SqlException - "The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Slaves_Masters_MasterId". The conflict occurred in database "EFExperiments", table "dbo.Masters", column 'Id'. The statement has been terminated."

我已经扫描了 SqlEception,它看起来既没有索引名称,也没有单独显示列名称的 table,只有消息。然而,最好将此错误解释为包含实体名称和类型的“ReferencedEntityNotFoundException”。这使得向用户显示友好消息解释发生的事情成为可能:

Master (id=123) does not exist anymore. Assign Slave to another one.

最好的方法是什么?是否可以使 SQL 服务器更详细,return table 和列的名称,或者我是否必须解析消息?是否存在用于此目的的任何 EF 扩展库?

P.S。还有一个选项可以完全删除 FK 约束并允许存在悬空从属,向用户显示它们具有无效状态。但这绝对是矫枉过正。

没有这样的库,但代码中那个地方出现的错误号 547 可能足以继续。

此外,您还可以在邮件中搜索特定的 FK 名称。从错误消息中提取对象名称应该是可靠的,因为它们是源代码的一部分,并且不依赖于语言。

例如:

catch (SqlException ex)
{
    foreach (SqlError e in ex.Errors)
    {
        if (e.Number == 547 && e.Message.Contains("FK_Slaves_Masters_MasterId") )
        {
            throw new ReferencedEntityNotFoundException("Master", "Slave", slave.MasterId);
        }
    }

    throw;    
}