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

11

在将数据库实体映射到模型并执行业务逻辑方面,最佳实践是什么?我看到了很多不同的实现方式。我注意到一些实现中,存储库(在数据层中)本身负责将数据库实体映射到域模型。例如,一个能够做到这一点的存储库:

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

综合搜索了许多关于N层设计的SO问题,我注意到虽然没有银弹,但在大多数情况下建议在MVC项目的控制器中手动映射或使用映射器执行映射。还反复强调,服务层不应执行映射,其责任应是执行业务逻辑。这里有几个问题:

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

编辑

哇,竟然有这么多关闭投票。抱歉,我没有充分搜索。我在这里提出的“在哪里执行业务逻辑”问题已经可以在SO和其他地方找到(尽管有时表达得有点隐晦):

Stephen Walther的Service Layer验证

Skinny Controllers

在此处查看SO上的另一个很棒但更通用的答案

我应该将我的控制器业务逻辑放在哪里

Service是否将实体映射到视图模型

然而,我尚未找到标准的解决方案来回答我之前提出的映射问题。我认为我可能可以更优美地表达我的问题。总体而言,业界一致认为业务逻辑应该在服务层中处理,并且将领域模型映射到视图模型应该在控制器/表示层中进行。由于不建议将DB实体暴露给除Data层以外的任何层,因此推荐在数据层手动或通过诸如Auto Mapper之类的映射器将实体映射到领域模型(这是我从阅读许多文章中得出的结论)。我的困惑来自于在哪里进行实体到领域模型的映射和领域模型到视图模型的映射的问题。但正如我之前所提到的,我可能可以更清楚地表达我的问题。我的困惑是因为我曾经读到过将实体映射到领域模型应该在控制器中进行,而这应该重新说成“将实体映射到领域模型应该在数据层进行,并且将领域模型映射到视图模型应该在控制器中进行。”

4个回答

4
  1. 在将实体映射到模型以及反之的问题上,哪种方法更可取?存储库应该这样做还是控制器应该进行映射?

我强烈建议在存储库中完成映射而不是在控制器中。正如Suhas在他的答案中提到的那样,控制器需要纯粹作为协调员。作为替代方案,您可以在存储库中使用映射类,该类传递实体并返回映射的模型 - 类似于Auto Mapper

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

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

总结:

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

1
数据访问层(存储库)应仅处理插入/更新/检索数据实体。您的服务层处理业务逻辑,并负责您的演示层(控制器,视图模型)与数据层之间的通信。这意味着您从数据实体到域的转换应在此层发生。您的演示层(控制器)应处理视图模型和域模型之间的转换。 -如果您想更好地了解,请采纳Maksym的建议并阅读《企业应用程序架构模式》,因为我认为(以及许多其他人也认为)Fowler是Web应用程序开发的权威。另一本好书是基于Fowler的书编写的ASP.NET设计模式,但仅集中于ASP.NET框架。

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

1

这要看情况而定... 就像你所说的,没有银弹。每种方法都有其优缺点,但最终你是最了解自己需求的人。 如果你有时间,我建议阅读这本书企业应用架构模式。这将让你对不同的业务逻辑和数据源架构模式有一个很好的理解,以及何时以及如何使用它们。什么应该放在业务层,什么应该放在DAL中。 此外,该书还解决了如何从DAL映射到域实体的问题。你甚至可能会改变主意,在长期内选择完全不同的方法。

另外,考虑使用一些ORM,例如EF Code First或NHibernate,提供给你代码优先机制。在这种情况下,所有映射逻辑都将对你透明。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接