【问题标题】:Where to put try catch在哪里放 try catch
【发布时间】:2010-10-06 03:36:10
【问题描述】:

考虑这种情况: 我有 3 层应用程序,当用户单击按钮时,按钮事件处理程序调用 biz 层中的一个方法,该方法对我的按钮事件处理程序提供的数据执行任何操作,然后将该数据传递给数据访问层,该数据访问层将它们发送到后端数据库。 问题是在哪里放置try catch?在数据层,在商务层,在表示层,或者可能把它放在所有这些层?在这种情况下,表示异常处理的最佳策略是什么?

【问题讨论】:

    标签: c# .net


    【解决方案1】:

    我们关注

    如果您不知道如何处理异常,请不要捕获它。

    我们从不处理任何我们无法处理或默认的异常。它会冒泡,我们在应用程序级别处理它。

    如果您可以为业务对象默认一个值,那么您可以在业务层中处理它。

    【讨论】:

    • 是的,在你能够处理的地方捕获异常。如果您不知道如何处理它,请不要抓住它。 (有时,“抓住它并忽略它”可能是正确的做法,所以这样做。)
    【解决方案2】:

    您只想使用 try catch 来管理未处理的代码。一个例子是我有一个正在与之通信的 COM 对象,我不希望它保持打开状态并造成内存泄漏。另一个可接受的替代方法是在允许异常继续之前捕获数据库中事件的错误。

    您永远不想使用 try catch 来处理您不确定自己的代码是否可以工作并需要备份计划的情况。

    那么,当应用程序崩溃时,您会遇到什么问题?使用自定义错误页面来指示您的 Web 应用程序中出现了问题,而对于胖客户端来说,它们会将代码解析到工作线程中,这样它们就不会破坏您的主线程失败。祝你好运!

    【讨论】:

      【解决方案3】:

      异常处理的口号是:“早扔,晚抓”。您想在可能的最后时刻捕获异常,但您想立即抛出它们(不要在确定有问题后执行更多处理然后抛出异常)。如果您无法“处理”异常,请不要捕获它。

      在大多数情况下,Try...Finally 块在您的代码中应该比 Try...Catch 更常见。

      【讨论】:

        【解决方案4】:

        当我有这样的多层架构(很多)时,我经常会在不止一层上尝试/捕获。例如,持久层中的 try/catch 捕获 SQLException,执行持久层需要执行的操作(例如通知管理员)然后抛出一个新异常,该异常对调用持久层的某些代码有意义.一个例子可能是 PersistenceException。下一层并不关心应该通知谁重新启动数据库,但它确实关心它无法保存用户状态,因此它可能会捕获 PersistenceException 并告诉用户他的新电话号码是' t 存储在数据库中。

        【讨论】:

          【解决方案5】:

          将 try-catch 放在您确定不会吞下异常的地方。如果可以保证一致性,在各个层中使用多个 try-catch 块可能是可以的。

          例如,您可以在数据访问层中放置一个 try-catch 以确保正确清理连接。但由于你不能在那里做更多的事情,你可能应该重新抛出异常。

          移动到业务层,您可以将 try-catch 放在多个您希望以原子方式进行的数据库操作中。在这种情况下,您可能应该回滚所有内容或将事物置于一致状态,在某处记录异常。应根据具体情况决定是否吞咽。

          您的表示层应始终捕获所有异常,无论是某些 Web 应用程序、在浏览器中运行的脚本还是某些富客户端应用程序。您可能无法完全理解异常,但至少可以确保您的应用程序不会在用户面前死掉。

          当然,这只是一个建议。 YMMV。 :)

          【讨论】:

          • 我想说,如果您担心清理 DAL 中的连接,您应该使用 Try-Finally 块(或使用块)而不是 Try-Catch。如果您只是要重新抛出异常而不处理它,则无需指定 Catch 块。
          • 哦,是的。抱歉,我的意思是最后尝试但没有注意到。 :(
          【解决方案6】:

          UI 仅用于演示。您不会在那里捕获异常,因为弄清楚如何处理它意味着逻辑。这属于业务或控制器层。在最坏的情况下,您会捕获异常并将其映射到适当的、用户友好的错误消息,然后将其发送到演示文稿进行显示。

          【讨论】:

            【解决方案7】:

            始终在顶层或控制器级别尝试/捕获。

            【讨论】:

              【解决方案8】:

              最好在所有层中使用 try catch,但只在 UI 层中静默捕获异常。在商业和数据访问层中,您可能应该在重新抛出之前捕获异常并记录信息,例如

              try
              {
                  //do something 
              }
              catch(Exception ex)
              {
                  LogFile.WriteLine(ex.ToString());
                  throw;
              }  
              

              注意:不要写:

              throw ex;
              

              因为这将从异常中清除所有有用的堆栈信息。

              【讨论】:

              • @mrdresser:为什么您应该在每一层中记录异常,而不是在我们处理异常/如果从未在 UI 层中处理过的所有地方都记录一次?堆栈跟踪将始终提供全部信息
              • 我和 Ramesh 合作。仅仅为了记录而抓捕是很诱人的……但这只是很多你不需要的繁忙工作,可以安全地避免。
              • 另外,如果你在每一层都记录它,你可能有多个日志条目用于同一个异常。
              • 我同意,只有例外一次。我根本不喜欢捕捉、记录和重新投掷的过程。这种类型的日志记录应该在更高级别进行处理,这样可以始终如一地完成,并且可以将逻辑应用于如何以及是否记录某些异常。
              【解决方案9】:

              一般的答案是:随时抓住你可以处理抛出的东西。也就是说,决定很简单。例如,捕获在创建所需对象时出现的异常。

              【讨论】:

                【解决方案10】:

                这仅取决于您实际上想在哪里做某事。通常我在业务层捕获它,然后记录它并可能调用一些 ui 函数向用户显示消息。

                我认为如何处理错误是一项业务规则。它应该与数据层或ui层分开。

                【讨论】:

                  【解决方案11】:

                  一定要在离用户最近的地方放置一个try catch——因为在那个位置你可以将它翻译成对你的用户有意义的东西。

                  只有在您打算对它们执行某些操作时才需要更深入的尝试捕获——例如,处理异常,或者可能记录并重新抛出异常。

                  【讨论】:

                    猜你喜欢
                    • 2022-01-13
                    • 1970-01-01
                    • 2016-07-02
                    • 2015-02-08
                    • 2012-11-29
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多