c# - 如何使用 EF6 和 SQL Server 捕获 UniqueKey Violation 异常?

标签 c# sql-server exception-handling entity-framework-6 unique-key

我的一个表有一个唯一键,当我尝试插入重复记录时,它会按预期抛出异常。但我需要将唯一键异常与其他异常区分开来,以便我可以自定义违反唯一键约束的错误消息。

我在网上找到的所有解决方案都建议将 ex.InnerException 转换为 System.Data.SqlClient.SqlException 并检查 if Number 属性等于 2601 或 2627,如下所示:

try
{
    _context.SaveChanges();
}
catch (Exception ex)
{
    var sqlException = ex.InnerException as System.Data.SqlClient.SqlException;

    if (sqlException.Number == 2601 || sqlException.Number == 2627)
    {
        ErrorMessage = "Cannot insert duplicate values.";
    }
    else
    {
        ErrorMessage = "Error while saving data.";
    }
}

但问题是,将 ex.InnerException 转换为 System.Data.SqlClient.SqlException 会导致无效转换错误,因为 ex.InnerException 是实际上是 System.Data.Entity.Core.UpdateException 类型,而不是 System.Data.SqlClient.SqlException

上面的代码有什么问题?如何捕获唯一键约束违规?

最佳答案

使用 EF6 和 DbContext API(用于 SQL Server),我目前正在使用这段代码:

try
{
  // Some DB access
}
catch (Exception ex)
{
  HandleException(ex);
}

public virtual void HandleException(Exception exception)
{
  if (exception is DbUpdateConcurrencyException concurrencyEx)
  {
    // A custom exception of yours for concurrency issues
    throw new ConcurrencyException();
  }
  else if (exception is DbUpdateException dbUpdateEx)
  {
    if (dbUpdateEx.InnerException != null
            && dbUpdateEx.InnerException.InnerException != null)
    {
      if (dbUpdateEx.InnerException.InnerException is SqlException sqlException)
      {
        switch (sqlException.Number)
        {
          case 2627:  // Unique constraint error
          case 547:   // Constraint check violation
          case 2601:  // Duplicated key row error
                      // Constraint violation exception
            // A custom exception of yours for concurrency issues
            throw new ConcurrencyException();
          default:
            // A custom exception of yours for other DB issues
            throw new DatabaseAccessException(
              dbUpdateEx.Message, dbUpdateEx.InnerException);
        }
      }

      throw new DatabaseAccessException(dbUpdateEx.Message, dbUpdateEx.InnerException);
    }
  }

  // If we're here then no exception has been thrown
  // So add another piece of code below for other exceptions not yet handled...
}

正如您提到的 UpdateException,我假设您使用的是 ObjectContext API,但它应该是相似的。

关于c# - 如何使用 EF6 和 SQL Server 捕获 UniqueKey Violation 异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31515776/

相关文章:

sql - 如何使用sql生成随机数?

haskell - 为什么 Haskell 异常只能在 IO monad 中捕获?

c# - Azure 存储 blob 无法加载文件或程序集“System.Diagnostics.DiagnosticSource,Version=4.0.4.0,Culture=neutral,PublicKeyToken=cc7b13ffcd”

c# - Azure 数据库的 DATEADD 函数

c# - 数据绑定(bind) WPF 中 WebBrowser 的 Source 属性

sql-server - Docker-compose MS SQL attach_dbs

c++ - 类成员初始化器抛出的异常是否应该调用 std::terminate()?

java - 重新抛出 InvocationTargetException 目标异常

c# - ASP.NET Timer 只在 Debug模式下工作

c# - 有条件地限制属性(property)访问