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

时间:2010-10-19 09:53:09

标签: c# entity-framework exception

当我将具有给定用户名的现有用户插入我的数据库时,我正在尝试捕获抛出的异常。正如标题所说,我正在使用EF。当我尝试将用户插入到db时抛出的唯一异常是“UpdateException” - 如何提取此异常以识别它是否是重复的异常或其他什么?

7 个答案:

答案 0 :(得分:38)

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

将正确的数字放在与唯一约束违规相对应的??????处(我不知道这是从头顶开始)。

答案 1 :(得分: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;
    }
}

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

答案 2 :(得分:13)

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

catch (UpdateException ex) when ((ex.InnerException as SqlException)?.Number == ??????)
{
    // Handle exception here
}

答案 3 :(得分:1)

如果您阻止异常发生,我认为会更好。如果可以使用您的代码,我会执行以下操作:

使用实体框架时,最好的办法是首先尝试使用LINQ的SingleOrDefault获取会给您带来麻烦的条目。现在,您可以使用要插入的实例更新已获取的实体,如果您使用它,则可以使用自动增量保护您的ID号。如果SingleOrDefault为null,您可以安全地添加您的实体。

代码示例:

    public override void AddOrUpdate(CustomCaseSearchCriteria entity)
    {
        var duplicateEntityCheck = GetSingleByUniqueConstraint(entity.UserCode, entity.FilterName);
        if (duplicateEntityCheck != null)
        {
            duplicateEntityCheck.Overwrite(entity);
            base.Update(duplicateEntityCheck);
        }
        else
            base.Add(entity);
    }

    public virtual CustomCaseSearchCriteria GetSingleByUniqueConstraint(string userCode, string filterName)
    {
        return GetAllInternal().SingleOrDefault(sc => sc.UserCode == userCode && sc.FilterName == filterName);
    }

答案 4 :(得分:1)

现在在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))
{

}

答案 5 :(得分:1)

如果您需要在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
    }
}

所有您需要做的就是从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();
    }
}

答案 6 :(得分:-1)

对于任何数据库类型,您都可以使用反射和相应的错误号(对于MySql 1062):

try
{
    var stateEntries = base.SaveChanges();
}
catch (Exception e)
{
    if(e is DbUpdateException)
    {
        var number = (int)e.InnerException.GetType().GetProperty("Number").GetValue(e.InnerException);
        if (e.InnerException!= null && (number == 1062))
        {
            //your handling stuff
        }
        else
        {
            messages.Add(e.InnerException.Source, e.InnerException.Message);
        }
    }
    else if (e is NotSupportedException || e is ObjectDisposedException || e is InvalidOperationException)
    {
        messages.Add(e.InnerException.Source, e.InnerException.Message);
    }
}