消除C#catch中的重复代码

时间:2015-12-29 22:48:57

标签: c# entity-framework

我的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))

但是我无法保证堆栈跟踪。有没有办法在没有大量重复代码的情况下保留堆栈跟踪?

4 个答案:

答案 0 :(得分:3)

我认为你有两个问题:

  1. 您只是为了将它们包装在您自己的异常类型中而捕获异常。为什么要这么麻烦?
  2. 你必须修改"几十个地方"如果你试图捕捉一个新的例外。这意味着您有一个漏洞抽象,并且您正在重复您的数据访问代码。
  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标记堆栈跟踪的位置,因此您要么抛出原始异常并将其捕获到其他位置,要么将其保留。

相关问题