C# 实体框架中的重复密钥异常?
我试图捕获在将具有给定用户名的现有用户插入数据库时引发的异常。正如标题所说,我正在使用EF。当我尝试将用户插入到db中时引发的唯一异常是“UpdateException”-我如何提取此异常以确定它是重复异常还是其他异常C# 实体框架中的重复密钥异常?,c#,entity-framework,exception,C#,Entity Framework,Exception,我试图捕获在将具有给定用户名的现有用户插入数据库时引发的异常。正如标题所说,我正在使用EF。当我尝试将用户插入到db中时引发的唯一异常是“UpdateException”-我如何提取此异常以确定它是重复异常还是其他异常 catch (UpdateException ex) { SqlException innerException = ex.InnerException as SqlException; if (innerException != null &&
catch (UpdateException ex)
{
SqlException innerException = ex.InnerException as SqlException;
if (innerException != null && innerException.Number == ??????)
{
// handle exception here..
}
else
{
throw;
}
}
将正确的数字放在与唯一约束冲突对应的??
(我不知道这是怎么回事)。现在在C#6.0中,您应该可以执行以下操作:
catch (UpdateException ex) when ((ex.InnerException as SqlException)?.Number == ??????)
{
// Handle exception here
}
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
}
}
因为我将EntityFramework与C#结合使用,所以我不得不对此做一点小小的更改-希望它能帮助任何人
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对象,该对象包含我需要的编号…我认为如果您阻止异常发生会更好。如果您的代码可行,我将执行以下操作: 当使用实体框架时,最好的做法是首先使用LINQ的SingleOrDefault尝试获取会给您带来麻烦的条目。现在,您可以使用要插入的实例更新获取的实体,如果您使用它,它会为您提供一个自动递增的ID号。如果SingleOrDefault为空,则可以安全地添加实体 代码示例:
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);
}
现在在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))
{
}
如果需要在Entity Framework Core中执行相同的操作,可以使用我构建的库,该库提供强类型异常,包括
UniqueConstraintException
:
它允许您捕获以下类型的异常:
catch (UpdateException ex) when ((ex.InnerException as SqlException)?.Number == ??????)
{
// Handle exception here
}
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安装它,并在您的onconfigurang
方法中调用它:
class DemoContext : DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<ProductSale> ProductSale { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseExceptionProcessor();
}
}
类DemoContext:DbContext
{
公共数据库集产品{get;set;}
公共DbSet ProductSale{get;set;}
配置时受保护的覆盖无效(DBContextOptions Builder Options Builder)
{
optionsBuilder.UseExceptionProcessor();
}
}
对于任何DB类型,您都可以使用反射和相应的错误号(对于MySql 1062):
与任何异常一样,查看innerexception以了解确切的错误详细信息。完美:)-但是。。我只是试图捕捉错误代码,它说重复条目的错误代码是-2146232060,这对我来说似乎有点奇怪?供将来参考:是唯一的约束冲突(对于SQL Server)。如果同时使用SQL Server和Oracle会怎么样?2601仅适用于SQLServer2601是“唯一索引”,2627是唯一约束谢谢,这很有帮助!我将使用这个,但是第7行有一个额外的空检查;如前所述,如果ex.InnerException(即第一个嵌套的InnerException)为null,则catch块将抛出NullReferenceException,ie ex.InnerException而不是ex.InnerException.InnerException。请注意,您的代码固有地暴露在竞速条件下,即有人可能在GetSingleByUniqueConstraint和duplicateEntityCheck.Overwrite()之间竞速插入一个条目。出于这个原因,您应该添加规定,以便在base.add()周围的catch块上执行更新;