在ASP.NET MVC中将实体映射到模型并执行业务逻辑

时间:2013-01-09 11:59:09

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

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

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

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

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

    哇这么多亲密的选票。道歉,我没有全面搜索。我在这里提出的“在哪里执行业务逻辑”这个问题已经可以在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)将实体映射到数据层的域模型(这是我从阅读很多文章)。我的困惑源于将实体映射到域模型以及将域模型映射到视图模型的问题。然而,正如我之前提到的,我可以更清楚地表达我的问题。我混淆的原因是我已经读过,映射实体到域模型应该在控制器中发生,这应该改为说“将实体映射到域模型应该在以后的数据中发生,并将域模型映射到视图模型应该在财务主任中进行。

4 个答案:

答案 0 :(得分:4)

  
      
  1. 关于将实体映射到何处,建议采用哪种方法   模型,反之亦然?存储库是应该这样做还是应该存在   映射是在控制器中完成的吗?
  2.   

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

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

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

要点:

  • Controller处理来自视图的请求并将其转发给 存储库
  • 存储库是数据存储的渠道
  • 服务处理来自存储库的请求,处理业务逻辑, 并返回映射模型

答案 1 :(得分:1)

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

答案 2 :(得分:1)

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

还要考虑使用一些ORM,它为您提供像EF Code First或NHibernate这样的Code First机制。在这种情况下,所有映射逻辑都将对您透明。

答案 3 :(得分:1)

数据访问层(存储库)应该只处理插入/更新/检索数据实体。 您的服务层处理业务逻辑,负责表示层(控制器,视图模型)与数据层之间的通信。这意味着您从数据实体到域的转换应该在此层进行。 您的表示层(控制器)应该处理视图模型和域模型之间的转换。 - 如果你想更好地理解,你应该考虑Maksym的建议并提取企业应用程序架构的模式,因为我认为(以及其他许多人)认为Fowler是Web应用程序开发的权威。另一本好书是ASP.NET设计模式,它基于福勒的书,但只集中在ASP.NET框架上。