EF Core 如何处理索引冲突问题的最佳实践

3

我需要处理来自SQL的不同类型的异常。在大多数情况下,这些异常来自于索引违规。

它至少包括:

  • DeleteBehavior.Restrict 违规
  • 唯一约束违规
  • 重复的键

我还没有找到任何关于正确处理此问题的相关内容。因此,我想出了以下解决方案:

try
{
    context.SaveChanges();
}
catch (Exception exception)
{
    if (exception.GetBaseException() is not SqlException sqlException) 
       throw;

    switch (sqlException.Number)
    {
        // Error codes we want to consider. The codes are for SQL Server provider.
        case 2627: // Unique constraint error
        case 547: // Constraint check violation
        case 2601: // Duplicated key row error
            // Checking if error message informing that an index was violated.
            // If so, this message will contain the name of index.
            if (sqlException.Message.Contains(IndexNames.MyIndexName))
            {
                // An example of error message:
                // Microsoft.Data.SqlClient.SqlException (0x80131904):
                // The INSERT statement conflicted with the FOREIGN KEY constraint "MyIndexName".
                // The conflict occurred in database "MyDatabase", table "dbo.Foo", column 'Id'.
                // The statement has been terminated.


                // Here I can do whatever I want knowing violated index name.
            }
        break;
    }
}

下面是工作正常的代码(测试过SQL Server),但它并不太可靠。例如,不同的数据库可能会以不同的方式显示错误。它们将具有不同的代码,因此您必须为每个数据库单独编写错误处理程序。

总的来说,在这种情况下,子字符串搜索对我来说看起来并不好。这似乎不是一个非常坚实且易于维护的解决方案。特别是当我们使用相当强大的EF Core框架时。

这个问题的目的是找到更优雅的方法来处理这种类型的错误,如果存在的话。


2
有一个名为DbUpdateException的类。请查看EntityFramework.Exceptions库。 - Alexander Petrov
请参阅“C# 6.0异常过滤器try catch when”:https://dev59.com/K1kT5IYBdhLWcg3wf_tN - Stefan Wuebbe
1个回答

3
这正是我创建 EntityFramework.Exceptions 库的原因。使用这个库,你不必处理不同的错误号码,只需做如下操作:
try
{
    context.SaveChanges();
}
catch (UniqueConstraintException e)
{
    //Handle unique exception here
}
catch (ReferenceConstraintException e)
{
    //Handle reference exception here
}

干得好!但是我不清楚如何确定违反的索引或约束条件?这是否与我在代码片段中使用string.Contains的方法相同? - Artem Balianytsia
1
@ArtemBalianytsia 没有简单的方法来确定那个。您需要使用字符串操作来获取该信息。 - Giorgi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接