我的C#6,.Net 4.6,Entity Framework 6应用程序在这个基本模式上有很多方法:
try
{
using (Entities dbContext = new Entities())
{
// Some database stuff
}
}
catch (System.Data.Entity.Core.EntityException eEntCore)
{
// May occur if connection to DB fails
throw MyApplicationException("Cannot access data store (Entity Core Exception)", eEntCore);
}
catch (System.Data.Entity.Infrastructure.DbUpdateException eDbu)
{
throw MyApplicationException("Cannot access data store (Database Exception)", eDbu);
}
catch (System.Data.SqlClient.SqlException eSql)
{
// Usually occurs after a Referential Integrity error
throw MyApplicationException("Cannot access data store (Data Exception)", eSql);
}
这些例外是我到目前为止发现的例外 - 可能还有更多。
我的问题是,如果出现另一个异常类型,我必须修改几十个方法来添加新的异常。我试图用这个catch块集中错误处理:
catch (Exception e)
{
AnalyseException(e);
}
AnalyseException()完成工作;它会抛出MyApplicationException或原始(未知)异常。除了堆栈跟踪之外的设计工作没有被保留(并且它承担了捕获异常的严重罪行。)
用户界面处理MyApplicationException。我不想让它处理所有不同的EF和SQL异常类型。
我尝试使用此C#6功能重新设计设计:
catch (Exception ex) when (AnalyseException(ex))
但是我无法保证堆栈跟踪。有没有办法在没有大量重复代码的情况下保留堆栈跟踪?
答案 0 :(得分:3)
我认为你有两个问题:
最好的解决方案是不要打扰包装异常。当你可以用它做一些有用的事情时捕获异常。
第二个最佳解决方案是保持您的异常处理相同(对我而言,老实说),并将数据访问逻辑封装在适当的接口之后。
答案 1 :(得分:1)
你只是在处理你不应该处理的异常。您应该只处理可以从中恢复的异常。这些例外无法恢复。他们将无法通过重试请求获得成功。
你不应该抓住那些例外。你应该允许它们在整个堆栈中冒泡。在堆栈的最顶层,您的全局异常处理应捕获这些未处理的异常,记录它们,并将通用服务器响应传达给客户端。
答案 2 :(得分:0)
按照最佳做法,您应该有一个常规异常块,用于捕获Exception
。在catch块中,您应该根据需要记录错误消息,然后调用throw;
。这将允许异常冒泡并向用户显示更有用的错误消息。
答案 3 :(得分:0)
我认为这可行:
try
{
using (Entities dbContext = new Entities())
{
// Some database stuff
}
}
catch (Exception ex)
{
if (!(ex is System.Data.Entity.Core.EntityException || ex is System.Data.Entity.Infrastructure.DbUpdateException || ex is System.Data.SqlClient.SqlException))
throw;
throw new MyApplicationException("Cannot access data store (" + ex.GetType().ToString() + ")", ex)
}
除非使用“throw”(不将其包装到您的异常类型中),否则无法保留堆栈跟踪。 throw标记堆栈跟踪的位置,因此您要么抛出原始异常并将其捕获到其他位置,要么将其保留。