实体框架中的重复关键异常?

ebb*_*ebb 28 c# entity-framework exception

我正在尝试捕获当我将具有给定用户名的已存在用户插入我的数据库时抛出的异常.正如标题所说,我正在使用EF.当我尝试将用户插入到db时抛出的唯一异常是"UpdateException" - 如何提取此异常以识别它是重复的异常还是别的?

Dar*_*rov 38

catch (UpdateException ex)
{
    SqlException innerException = ex.InnerException as SqlException;
    if (innerException != null && innerException.Number == ??????)
    {
        // handle exception here..
    }
    else
    {
        throw;
    }
}
Run Code Online (Sandbox Code Playgroud)

将正确的数字放在??????与唯一约束违规相对应的数字上(我不知道从头到尾).

  • 供将来参考:[2601](http://msdn.microsoft.com/en-us/library/aa258747(v = sql.80).aspx)是一种唯一的约束违规(对于SQL Server). (13认同)
  • 2601是"唯一索引",2627是唯一约束[link](http://stackoverflow.com/a/6483854/823247) (10认同)
  • 如果同时使用SQLServer和Oracle怎么办?2601 仅适用于 SQLServer (3认同)

小智 14

因为我在C#中使用EntityFramework,所以我不得不对此做一点改动 - 希望它对任何人有帮助......

try
{
    await db.SaveChangesAsync();
}
catch (DbUpdateException ex)
{
    SqlException innerException = ex.InnerException.InnerException as SqlException;
    if (innerException != null && (innerException.Number == 2627 || innerException.Number == 2601))
    {
        //your handling stuff
    }
    else
    {
        throw;
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是因为我需要DbUpdateException而不是UpdateException,而我的InnerException对象有一个额外的InnerException对象,其中包含我需要的数字......

  • 如果我只进入一层,即 ex.InnerException 而不是 ex.InnerException.InnerException,这对我有用。 (2认同)

pet*_*ski 13

现在在C#6.0中你应该能够做到这样的事情:

catch (UpdateException ex) when ((ex.InnerException as SqlException)?.Number == ??????)
{
    // Handle exception here
}
Run Code Online (Sandbox Code Playgroud)


小智 9

现在在 C# 7 中,您可以使用 is 运算符

// 2627 is unique constraint (includes primary key), 2601 is unique index
catch (UpdateException ex) when (ex.InnerException is SqlException sqlException && (sqlException.Number == 2627 || sqlException.Number == 2601))
{

}
Run Code Online (Sandbox Code Playgroud)


Gio*_*rgi 9

如果您需要在 Entity Framework Core 中执行相同的操作,您可以使用我构建的库,该库提供强类型异常,包括UniqueConstraintExceptionEntityFramework.Exceptions

它允许您捕获类型异常,如下所示:

using (var demoContext = new DemoContext())
{
    demoContext.Products.Add(new Product
    {
        Name = "a",
        Price = 1
    });

    demoContext.Products.Add(new Product
    {
        Name = "a",
        Price = 10
    });

    try
    {
        demoContext.SaveChanges();
    }
    catch (UniqueConstraintException e)
    {
        //Handle exception here
    }
}
Run Code Online (Sandbox Code Playgroud)

您所要做的就是从 Nuget 安装它并在您的OnConfiguring方法中调用它:

class DemoContext : DbContext
{
    public DbSet<Product> Products { get; set; }
    public DbSet<ProductSale> ProductSale { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseExceptionProcessor();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我知道回答指向库的编码问题通常是不正确的,但在这种情况下,我强烈认为这是正确的解决方案。对于这种情况,在 EF 级别存在抽象是有意义的,而不是将数据库提供程序抽象泄漏到客户端代码中。毕竟,我们一开始就没有 SQL Server 特定的代码来设置主键/唯一约束,那么为什么违规检测应该是 SQL Server 特定的呢?我宁愿它被烘焙到 EF 中,但我很高兴接受这种依赖。 (5认同)