C# 我应该在哪里处理BLL、DAL或PL中的异常?

C# 我应该在哪里处理BLL、DAL或PL中的异常?,c#,.net,architecture,layered,C#,.net,Architecture,Layered,哪一个是处理异常的最佳位置?BLL、DAL还是PL 我是否应该允许DAL和BLL中的方法向上抛出异常并让PL处理它们?或者我应该在BLL处理他们 e、 g 如果DAL中有一个方法发出“ExecuteOnQuery”并更新一些记录,并且由于一个或多个原因,0行受到影响。现在,我应该如何让PL知道是否发生了异常,或者是否确实没有与条件匹配的行。我应该在PL代码中使用“try catch”并通过异常告知它,还是应该在DAL中处理异常并返回一些特殊代码,如(-1),以让PL区分(异常)和(无行匹配条件,

哪一个是处理异常的最佳位置?BLL、DAL还是PL

我是否应该允许DAL和BLL中的方法向上抛出异常并让PL处理它们?或者我应该在BLL处理他们

e、 g


如果DAL中有一个方法发出“ExecuteOnQuery”并更新一些记录,并且由于一个或多个原因,0行受到影响。现在,我应该如何让PL知道是否发生了异常,或者是否确实没有与条件匹配的行。我应该在PL代码中使用“try catch”并通过异常告知它,还是应该在DAL中处理异常并返回一些特殊代码,如(-1),以让PL区分(异常)和(无行匹配条件,即受影响的零行)

知道如何正确设置的层应该是处理异常的层。
例如,如果您决定通过多次重试查询来处理死锁错误,那么您可以将其构建到DAL中。如果它继续失败,那么您可能希望让异常冒泡到下一层,然后由下一层决定它是否知道如何正确处理此异常。

您的问题是异常与何处相关?如果是数据访问异常,则应在DAL中捕获。如果是逻辑异常,则应在BLL中捕获。如果是表示异常,则在PL中

例如,如果DAL抛出异常,它应该向BLL返回null或false或任何情况。如果DAL返回null,您的BLL应该知道该怎么做,可能它会直接传递,可能它会尝试调用另一个函数,等等。您的PL也应该知道这一点。如果BLL从DAL传递null或返回自己的特定内容,那么表示层应该能够通知最终用户出现了问题

当然,您不会得到详细的异常消息,但对于您的用户来说,这是一件好事。您应该有一个灵活的日志系统来捕获这些异常,并将它们报告给数据库或ip:port或您决定的任何东西


基本上,您需要考虑问题是数据问题还是逻辑问题,应该相应地进行处理。

简短的回答是,这取决于

只有当你能做一些有用的事情时,你才应该处理一个异常。“有用的东西”同样取决于你在做什么。您可能希望记录异常的详细信息,尽管这并不能真正处理异常,而且在大多数情况下,您应该在登录后重新抛出异常。您可能希望将异常包装到其他(可能是自定义)异常中,以便向异常添加更多信息。当@mbeckish打开时,您可能希望通过重试该操作来尝试从异常中恢复,例如,您应该小心不要永远重试。最后(请原谅这个双关语),您可能希望使用Finally块来清理任何资源,例如开放数据库连接。您选择如何处理异常将影响您处理异常的方式。除了向用户报告发生了错误之外,在许多异常情况下可能没有很多有用的事情可以做。在这种情况下,在UI层处理异常并向用户报告问题是完全可以接受的(您可能还应该记录该异常,进一步记录您的层)

当您自己抛出异常时,您应该只在“异常”情况下抛出异常,因为抛出异常会带来很大的开销。在您的示例中,您建议如果您的操作没有更新任何记录,您可能会考虑抛出异常。这真的是异常吗?在这种情况下,更好的做法是e返回更新的记录数-这可能仍然是一个需要向用户报告的错误情况,但并不例外,例如命令失败,因为与数据库的连接已断开


这是一篇关于异常处理最佳实践的合理文章。

这是一个巨大的话题,有许多不必要的争议(声音大的人给出不好的信息!)如果你愿意处理这个问题,请遵循s1mm0t的建议,这基本上是可以接受的

但是,如果您想要一个单词的答案,请将其放在PL.SEARY中。如果您可以侥幸逃脱,请将错误处理放在全局异常处理程序中(出于安全原因,所有错误都应记录并提供代码以在生产中查找日志(尤其是在web上),但出于速度原因,请在开发过程中提供完整的详细信息)

编辑:(澄清)您必须处理所有地方的一些错误-但这不是“每个函数”的标准。大多数情况下,让它们冒泡到PL并用您自己的代码处理.NET的全局错误:通过一个公共例程记录完整的调用堆栈,该例程可通过事件处理程序从所有3层访问(请参阅消息底部的编辑)。这意味着您将让try/catch贯穿您的所有代码;只包含您期望的部分和错误,并可以立即处理,或者非关键部分,您可以使用这些部分记录错误并通知用户不可用的功能(这对于超级可靠/关键程序来说更为罕见)

除此之外,在处理有限的资源项时,我经常使用'using'关键字或try/finally/end try而不使用catch。对于多线程锁/互斥锁/重入防止标志/等,在所有情况下都需要try/finally,以便程序仍能工作(尤其是有状态的应用程序)

如果您不正确地使用了异常(例如,当您应该使用If语句或检查它时,为了处理非bug,在您尝试它之前,一个不确定的操作会起作用),这一理念将更加分崩离析

另外,在厚客户端应用程序中,尤其是在可能的情况下