【问题标题】:Mapping Entities to Models and Performing Business Logic in ASP.NET MVC在 ASP.NET MVC 中将实体映射到模型并执行业务逻辑
【发布时间】:2012-12-23 11:19:11
【问题描述】:

将数据库实体映射到模型和执行业务逻辑的最佳做法是什么?我已经看到了两者的相当不同的实现。我注意到许多实现,其中存储库(在数据层中)本身负责将数据库实体映射到域模型。例如,可以执行此操作的存储库:

public IQueryable<Person> GetPersons()
{
      return DbSet.Select(s => new Person
                    {
                        Id = s.Id,
                        FirstName= s.FirstName,
                        Surname= s.Surname,
                        Location = s.Location,
                    });
}

但是在对 SO on N Tier 设计进行全面搜索后,我注意到虽然没有灵丹妙药,但在大多数情况下,建议手动或使用映射器在 MVC 项目中的控制器内部执行映射。还重申了服务层永远不应该执行映射,它的职责应该是执行业务逻辑。这里有几个问题:

  1. 在将实体映射到模型的位置(反之亦然)方面,哪种方法是可取的?存储库应该这样做还是应该在控制器中完成映射?
  2. 假设我想对从数据库中检索到的实体执行一些业务逻辑,例如返回Person实体的全名,或者将所有Persons的年龄增加10年,应该在哪里执行此操作。在模型本身?例如,我会在模型上有一个FullName 属性来计算全名和年龄吗?还是在我的服务层中定义一些服务来执行业务逻辑?

编辑

哇,这么多票数接近。抱歉,我搜索的不够全面。我在这里提出的“在哪里执行业务逻辑”问题已经可以在 SO 和其他地方找到(尽管有时传达得有些神秘):

Validating with a Service Layer by Stephen Walther

Skinny Controllers

Another great, but more generic answer here on SO

Where Should I put My Controller Business Logic in MVC

Does a Service Map Entities to a View Model

但是,我还没有找到解决我所遇到的映射问题的标准解决方案,我想我或许可以更雄辩地表达我的问题。所以普遍的共识似乎是业务逻辑进入服务层,将领域模型映射到视图模型应该发生在控制器/表示层。并且由于建议不要将您的数据库实体显示到数据层以外的任何层,因此建议您手动或通过诸如 Auto Mapper 之类的映射器将您的实体映射到数据层的域模型(这是我从阅读许多文章)。我的困惑源于应该将实体映射到域模型以及将域模型映射到视图模型的问题。然而,正如我之前提到的那样,我本可以更清楚地表达我的问题。我感到困惑的原因是我已经读过将实体映射到域模型应该发生在控制器中,这应该改写为“将实体映射到域模型应该稍后发生在数据中,并将域模型映射到视图模型应该在 Controller 中进行。

【问题讨论】:

    标签: asp.net-mvc architecture n-tier-architecture


    【解决方案1】:
    1. 在将实体映射到何处时,建议使用哪种方法 模型,反之亦然?存储库应该这样做还是应该 映射在控制器中完成?

    我强烈希望看到映射发生在存储库中,而不是控制器中。正如 Suhas 在他的回答中提到的那样,控制器需要纯粹充当协调员。作为替代方案,也许您可​​以利用存储库中的映射类来传递实体并返回映射模型 - 有点像 Auto Mapper

    1. 假设我想对我的实体执行一些业务逻辑 已从数据库中检索到,例如返回全名 Person 实体,或将所有 Person 的年龄增加 10 岁, 应该在哪里执行此操作。在模型本身?为了 例如,我是否会在模型上有一个 FullName 属性 计算全名和年龄?还是我在里面定义一些服务 我的服务层来执行业务逻辑?

    如果可能,请在服务上执行业务逻辑。为什么要让应用程序承担服务层应该做的事情?我相信这是服务的域,而不是应用程序的域。另外,我也不认为从模型返回连接或派生的属性是一件坏事。

    总结:

    • 控制器处理来自视图的请求并将它们转发给 存储库
    • 存储库是您的数据存储的管道
    • 服务处理来自存储库的请求,处理业务逻辑, 并返回映射模型

    【讨论】:

      【解决方案2】:

      数据访问层(存储库)应该只处理插入/更新/检索您的数据实体。 您的服务层处理业务逻辑并负责表示层(控制器、视图模型)和数据层之间的通信。这意味着您从数据实体到域的转换应该发生在这一层。 您的表示层(控制器)应该处理您的视图模型和域模型之间的转换。 -如果你想有更好的理解,你应该接受 Maksym 的建议和拾取企业应用程序架构模式,因为我认为(和许多其他人)认为 Fowler 是 Web 应用程序开发的权威。另一本好书是 ASP.NET Design Patterns,它基于 Fowler 的书,但只关注 ASP.NET 框架。

      【讨论】:

        【解决方案3】:

        这取决于... 就像你说的,没有灵丹妙药。只能列出每种方法的优缺点,但仍然是您比这里的任何人都更了解您的需求。 如果您有时间,我建议您阅读本书Patterns of Enterprise Application Architecture。这将使您对不同的业务逻辑和数据源架构模式、何时以及如何使用它们有一个很好的理解。什么应该去业务层,什么应该去 DAL。 本书还解决了如何从 DAL 映射到域实体的问题。从长远来看,您甚至可能改变主意并选择完全不同的方法。

        还可以考虑使用一些 ORM,它为您提供代码优先机制,如 EF Code First 或 NHibernate。在这种情况下,所有映射逻辑对您来说都是透明的。

        【讨论】:

          【解决方案4】:

          我通常在 MVC 项目中创建一个小型服务层来处理 MVC 层需要完成的额外工作。因此,在您的示例中,您可以使用 PersonServicePersonHandler 调用业务层以获取所有人员实体,然后将所有人的年龄增加 10 年(假设这不是您的业务逻辑,而只是UI 需要的东西),连接名字和姓氏以构建全名等。控制器然后只是调用此服务,并且永远不知道幕后发生了什么。这样,您的控制器就在做它应该做的事情——在视图和模型之间进行协调。

          【讨论】:

            猜你喜欢
            • 2018-11-10
            • 1970-01-01
            • 2011-04-15
            • 2011-09-03
            • 1970-01-01
            • 2012-04-25
            • 1970-01-01
            • 1970-01-01
            • 2015-07-30
            相关资源
            最近更新 更多