【问题标题】:ASP.NET MVC - Exception throw?ASP.NET MVC - 异常抛出?
【发布时间】:2011-04-24 12:33:46
【问题描述】:

我有一个通用存储库 - 存储库应该能够抛出异常还是应该让它保持沉默?如果我选择从中抛出异常,那么服务层是否应该在它到达 Controller 之前捕获它并抛出带有更友好消息的异常?

  • Pos1:存储库(抛出)=> 服务(捕获,抛出新)=> 控制器(捕获)
  • Pos2:存储库 => 服务(抛出)=> 控制器(捕获)

【问题讨论】:

    标签: asp.net-mvc exception architecture design-patterns


    【解决方案1】:

    绝对是选项 1。

    在您的想法中,我还将用“关注点分离”替换“愚蠢”一词。存储库没有理由愚蠢。它有工作要做,这将涉及异常。

    这也将涉及扔它们,原因有两个:

    1. 打包消费代码发生的真正错误。

    2. 在给定条件下抛出异常,违反您希望此类执行的操作。这些条件可能不涉及框架引发的异常,并且可能仅与您希望存储库拥有的“智能”相关。

    存储库必须涉及封装所有这些智能,让调用代码只需要知道如何处理一组有限的异常。否则,您的调用代码需要处理,例如,完整的 LINQ 异常,将其耦合到应该是存储库专有域的技术。

    因此,存储库的部分智能必须抛出与其特定目的相关的众所周知但有限的一组异常。

    同样的推理也适用于服务层,如果你有的话。它需要以完全相同的方式处理异常:封装特定于其任务的“智能”。同样,控制器也会发生同样的情况。它应该根据自己的目的和关注点来解释它从服务层接收到的异常(如果有的话)。

    关注点分离,但绝不愚蠢。甚至没有静音:每一层都需要在必要时发出尖叫声。

    【讨论】:

      【解决方案2】:

      存储库是否应该能够抛出 例外还是我应该保持沉默?

      是的 - 存储库应该能够抛出异常。保持“愚蠢”并不意味着它没有完全自我意识:)

      “例外应该是例外”的警告仍然适用 - 您可能会发现这篇“Creating More Exceptional Exceptions”文章感兴趣,它也与您的问题相关。

      如果我选择从 它,应该服务层然后 抓住它并抛出异常 在它离开之前更友好的信息 到控制器?

      一般来说,我不会重新抛出异常,尽管这样做是有好处的。一个务实的折衷办法是对出于某种原因想要优雅处理的异常类型执行此操作。

      如果您使用的是 Ms Ent Libs 应用程序日志记录块之类的东西,您可以设置一个策略(通过配置),允许您控制异常发生时发生的情况 - 重新抛出异常或以其他方式;所以这将是一种有用的方法,可以停止将自己硬编码到特定结果中。

      这可能也很有趣:Are exceptions really for exceptional errors?

      【讨论】:

        【解决方案3】:

        一般来说,如果您的查询没有返回数据,您应该简单地从您的存储库中返回 null。然后,如果您愿意,您可以在将数据发送到您的视图之前测试存储库中的空值。

        public ActionResult Details(int id) {
        
            Dinner dinner = dinnerRepository.FindDinner(id);
        
            if (dinner == null)
                return View("NotFound");
            else
                return View("Details", dinner);
        }
        

        http://nerddinnerbook.s3.amazonaws.com/Part4.htm

        对于编辑,我会让您的数据访问层或存储库抛出异常,并在控制器中捕获它,如下所示:

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(int id, FormCollection formValues) {
        
            Dinner dinner = dinnerRepository.GetDinner(id);
        
            try {
        
                UpdateModel(dinner);
        
                dinnerRepository.Save();
        
                // Success!
                return RedirectToAction("Details", new { id=dinner.DinnerID });
            }
            catch {
        
                // Old-school data validation from ASP.NET MVC 1.0
                foreach (var issue in dinner.GetRuleViolations()) {
                    ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage);
                }
        
                // Return original view, so user can correct errors.
                return View(dinner);
            }
        }
        

        http://nerddinnerbook.s3.amazonaws.com/Part5.htm

        【讨论】:

        • 如果我需要更新记录怎么办......那么我必须在我的存储库或服务中抛出异常?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多