如何从SQL Server 2008错误代码中识别主键重复?

时间:2013-03-05 07:02:44

标签: c# sql-server entity-framework

我想知道如何识别C#中SQL Server错误代码的主键重复错误。

作为一个例子,我有一个C#表单将数据输入到SQL Server数据库中,当数据输入时发生错误时,如何从异常中识别出错误的原因?

4 个答案:

答案 0 :(得分:51)

如果您抓住SqlException然后查看其编号,则数字2627将表示违反唯一约束(包括主键)。

try
{
    // insertion code
}
catch (SqlException ex)
{
    if (ex.Number == 2627)
    {
        //Violation of primary key. Handle Exception
    }
    else throw;
}

MSSQL_ENG002627

  

这是一个可以提出的一般错误,无论是否a   数据库被复制。在复制的数据库中,错误是   通常会引发,因为拓扑中没有正确管理主键

答案 1 :(得分:4)

这是一个老线程,但我想值得注意的是,因为C#6你可以:

try
{
    await command.ExecuteNonQueryAsync(cancellation);
}
catch (SqlException ex) when (ex.Number == 2627)
{
    // Handle unique key violation
}

使用C#7和包装异常(如Entity Framework Core):

try
{
    await _context.SaveChangesAsync(cancellation);
}
catch (DbUpdateException ex) 
   when ((ex.InnerException as SqlException)?.Number == 2627)
{
    // Handle unique key violation
}

与接受的答案相比,这种方法的最大优点是:

如果错误编号等于2627,因此,它不是唯一的密钥违规,则不会捕获异常。

如果没有例外过滤器(when),您最好记住重新抛出该异常,以防您无法处理。理想情况下,不要忘记使用ExceptionDispatchInfo,以免原始堆栈丢失。

答案 2 :(得分:0)

在实体框架的情况下,接受的答案将不起作用,错误将最终没有被捕获。这是一个测试代码,如果实体语句被删除,则只会触发实体catch语句,或者当然是通用异常:

try
{
    db.InsertProcedureCall(id);
}
catch (SqlException e0)
{
   // Won't catch
}
catch (EntityCommandExecutionException e1)
{
    // Will catch
    var se = e1.InnerException as SqlException;
    var code = se.Number;
}
catch (Exception e2)
{
   // if the Entity catch is removed, this will work too
    var se = e2.InnerException as SqlException;
    var code = se.Number;
}

答案 3 :(得分:0)

仅用于过滤器的工作代码重复的主键冲突异常

using System.Data.Entity.Infrastructure;
using System.Data.SqlClient;
.........

 try{
    abc...
    }
    catch (DbUpdateException ex)
                {
                    if (ex.InnerException.InnerException is SqlException sqlEx && sqlEx.Number == 2601)
                    {
                        return ex.ToString();
                    }
                    else
                    {
                        throw;
                    }
                }

注意细节:-ex.InnerException.InnerException而不是ex.InnerException