我有一个名为
Announcement
的表,它在列 Title
和 Code
上有唯一索引。
我正在使用 Entity Framework 6.0.26 进行 CRUD 操作,但在将数据插入/更新到上述列时遇到问题。
catch (Exception ex)
{
if (ex.InnerException!.Message.Contains("unique index"))
{
if (ex.InnerException.Message.Contains("IX_Announcement_Code"))
{
throw new Exception("this code is already used");
}
if (ex.InnerException.Message.Contains("IX_Announcement_Title"))
{
throw new Exception("this title is already used");
}
}
throw new Exception();
}
我正在使用这段代码来找出引发异常的原因 - 无论是否因为索引,但我知道这样做是一个不好的做法。
是否有与表索引相关的异常?
我知道我可以创建自定义方法进行验证(例如
Task<bool> TitleAlreadyExists(string title)
),但这不是我想要的。
我正在寻找更好的解决方案来处理数据库表索引异常。
考虑您的具体请求到“[我正在寻找]更好的解决方案来捕获此异常”:
捕获最具体的异常类型合理:
catch (DbUpdateException ex)
执行合理的健全性检查(也许使用异常过滤器 - 但当然你可以嵌套它)
catch (DbUpdateException ex) when ( ex.InnerException is null )
{
// throw an application-specific Exception type
throw new ApplicationUpdateFailedException(ex.Entries);
}
继续检测您的特殊情况
catch (DbUpdateException ex) when ( ex.InnerException is null )
{
// throw an application-specific Exception type
throw new ApplicationUpdateFailedException(ex.Entries);
}
catch (DbUpdateException ex) when ( ex.InnerException is not null &&
ex.InnerException.Message.Contains("IX_Announcement_Code"))
{
// throw an application-specific Exception type
throw new ApplicationUpdateFailedDuplicateCodeException(ex.Entries);
}
catch (DbUpdateException ex) when ( ex.InnerException is not null &&
ex.InnerException.Message.Contains("IX_Announcement_Title") )
{
// throw an application-specific Exception type
throw new ApplicationUpdateFailedDuplicateTitleException(ex.Entries);
}
为了使其更具可读性,您可能需要引入一些扩展方法,例如
internal static class DbUpdateExceptionExtensions
{
internal static bool IsConflictForIndex(this DbUpdateException ex, string indexName) =>
ex.InnerEcxeption is not null &&
ex.InnerException.Message.Contains(indexName);
}
然后
catch (DbUpdateException ex) when ( ex.InnerException is null )
{
// throw an application-specific Exception type
throw new ApplicationUpdateFailedException(ex.Entries);
}
catch (DbUpdateException ex) when ( ex.IsConflictForIndex("IX_Announcement_Code"))
{
// throw an application-specific Exception type
throw new ApplicationUpdateFailedDuplicateCodeException(ex.Entries);
}
catch (DbUpdateException ex) when ( ex.IsConflictForIndex("IX_Announcement_Title") )
{
// throw an application-specific Exception type
throw new ApplicationUpdateFailedDuplicateTitleException(ex.Entries);
}
所有这些都假设您拥有特定于应用程序的异常类型,它们也可能形成继承树,因此您可以稍后决定是要单独捕获每个异常还是作为一组错误捕获。
单独说明:
这不是一个好主意这样做
catch(Exception ex) // too broad anyway , ... but
{
if( yadda yadda )
{
// ...
throw new Exception("Message");
}
throw new Exception(); // Stacktrace reset, no message, ... == "Something went wrong" == useless
}
您正在失去有价值的信息。如果您首先必须做类似的事情,您可能需要考虑做类似的事情:
catch(Exception ex) // too broad anyway , ... but
{
if( yadda yadda )
{
// ...
throw SomethingElseException(ex);
}
throw;
}