2015-06-21 81 views
1

我有以下情形,我调用一个方法在我的数据访问代码从我的业务层:在DALtry catch块位置

//Call the method from BL 
SqlHandler sh = new SqlHandler(); 
var names = sh.GetNames(); 

方法例如:

public IEnumerable<string> GetNames() 
{ 
    string conString = GetOpenConnection(); 
    using (SqlConnection connection = new SqlConnection(conString)) 
    { 
     connection.Open(); 
     using(SqlCommand cmd = new SqlCommand("SELECT Name From Names")) 
     { 
      //... 
     } 
    } 
} 

我需要是记录我的DAL中发生的任何异常,并使用适当的消息向用户显示消息。据我可以看到我有下列选项:

1)仅包围BL呼叫和记录和显示从那里消息:

try 
{ 
    SqlHandler sh = new SqlHandler(); 
    var names = sh.GetNames(); 
} 
catch (Exception ex) 
{ 
    ex.LogException(); 
    MessageBox.Show(ex.Message); 
} 

2)环绕两个呼叫,分裂记录部分和通知部分分成2个部分:

try 
{ 
    SqlHandler sh = new SqlHandler(); 
    var names = sh.GetNames(); 
} 
catch (Exception ex) 
{ 
    MessageBox.Show(ex.Message); 
} 

public IEnumerable<string> GetNames() 
{ 
    try 
    { 
     string conString = GetOpenConnection(); 
     using (SqlConnection connection = new SqlConnection(conString)) 
     { 
      connection.Open(); 
      using (SqlCommand cmd = new SqlCommand("SELECT Name From Names")) 
      { 
       //... 
      } 
     } 
    } 
    catch (Exception ex) 
    { 
     ex.LogException(); 
     //propagate the exception to the caller 
     throw; 
    } 
} 

3)当然,我可能失去了一些东西,我会很乐意了解

什么是首选Appro公司在这里的应用程序架构方面?前两者之间是否有功能差异?

+2

这是基于意见的.. –

+0

是你的问题“我应该把try {} catch {}'块放到DAL或BAL中吗? – hdoghmen

+0

选项1看起来不错...您可能需要像http://stackoverflow.com/a/136092/747609这样的东西来处理不同的事情。尽管如此,这可能会很麻烦。 – IROEGBU

回答

2

我建议第三个选项:把错误记录和错误显示在UI层。

在您的用户界面中注册一个central error handler。在那里,你可以

  • 显示错误(无论是简单的MessageBox或用“更多细节”看中窗口和按钮“以开发报告”)和

  • 日志一切,

不必杂乱带有全部try-catch子句的BL方法。

这有很多优点:

  • 它会使你的BL代码更易于阅读。
  • 你不能忘记一个BL方法。
  • 更容易对错误处理代码进行(集中式)更改。
  • 您不会将您的业务逻辑与特定类型的用户界面耦合在一起,这对用户界面有很多好处:例如,您可以稍后在基于Web的项目中重用它,并且可以测试您的业务逻辑与单元测试
+0

然而,这是一个有趣的方法,如果在调用异常倾向方法后,我怎么能知道它是否成功(_i.e_我应该重试调用还是停止执行其余代码并返回)? – Yoav

+0

@Yoav:* Ususally *,异常是您无法从中合理恢复的意外情况。我建议在个案的基础上处理特殊情况:如果你有一个非常具体的方法,你知道它有时会抛出一个非常特殊的异常(以及你知道如何处理它,例如重试),那么我会在try-catch块中包装这个*(只有这个)方法来捕获* this *(并且只有这个)异常(即'catch(MyExpectedDeadlockException)'而不是'catch(Exception)')并且做一些事情针对这种情况。 – Heinzi

+0

@Yoav:对于所有其他类型的异常,中断BL操作,记录,显示消息并返回到UI是正确的。而这正是这种方法的作用。 – Heinzi

0

首先:总是赶只有异常,您可以处理(See Eric Lippert Post
你可以按照这个策略:

  • 如果不能从异常恢复做在DAL层只并记录下来。
  • try {} catch{}如果用户可以处理它在BAL层。
+0

我并不完全同意这种看法,只会捕捉你可以处理的异常。有一些类型的例外是你不能指望的,或者是不值得花时间来尝试和预测的,例如数据库相关的或TCP相关的例外情况,你仍然希望让应用程序\用户在投掷前重试 – Yoav

+0

@Yoav如果你有意想不到的例外,让他们崩溃你的过程。这样,你会意识到它们存在并迫使你处理它们,而不是保持登录在某个txt文件 –

+0

@YuvalItzchakov所以你会建议不围绕数据库操作(当然,让事务离开)? – Yoav