领域实体、数据传输对象(DTO)和视图模型

18

我有一个ASP.NET MVC 2应用程序,具有POCO域模型和NHibernate存储库层。我的域模型没有意识到我的视图模型,因此我使用automapper从视图模型转换到实体,反之亦然。

当我向项目引入WCF(晚期要求)后,我开始处理断开连接的对象。也就是说,我使用NHibernate从数据库检索实体,一旦该实体被序列化,它就变得与数据库断开连接,并且每个子集合都会被加载,无论我是否计划使用它,这意味着我正在做很多不必要的数据库工作。

阅读了相关资料后,我发现强烈建议您不要在域项目之外公开实体,而是应使用数据传输对象(DTOs)。

我理解这个原因,但我无法确定如何实施。

我应该在ASP.NET MVC中从视图模型映射到DTO,在服务层中传递DTO并从DTO映射到实体吗? 我应该在哪里定义我的DTO?

4个回答

17

我喜欢让我的服务层将实体封装在其中,并仅返回/接收DTO。我将服务契约以及DTO都放在一个单独的程序集中,MVC项目和服务实现都引用该程序集。

在服务调用实现中,服务将DTO映射到实体,然后根据需要与存储库和其他实体进行交互。

在应用程序/MVC项目中,有时我会变懒,只使用DTO作为某些操作的模型(特别是CRUDy操作)。如果需要投影或类似的东西,则使用Automapper等转换DTO和视图模型之间。

实体暴露的程度是一个广受争议的问题。有些人会将它们推到视图/应用程序层。我更喜欢将它们保留在服务层中。当实体离开服务层时,您会发现自己正在任何与之交互的地方执行业务逻辑类型的操作,这些操作可能应该驻留在服务中。


这绝对是最适合我情况的 - 我没有意识到这个问题上有争议。我发现将我的实体暴露在服务层之外会导致麻烦 - 但直到我将WCF添加到项目中,我才开始遇到这些问题。 - Mayo
1
我认为,如果您的应用程序不是分布式的(应用程序和服务层之间没有网络间隔),那么这就不是一个很大的问题。我看过微软的文章,他们提倡在应用程序的所有层中使用实体。我也经常在“alt.net”类型的文章中看到上述结构,并且对我来说效果更好。它还简化了我的应用程序思考方式,服务确实是进入领域的入口。 - Brook

2
我将我的DTO视为ViewModel,因为UI层(MVC应用程序)正在请求它们。您可以使用Entity->DTO->ViewModel,但我认为如果服务的唯一使用者是MVC应用程序,则这是过度工程化的。如果DTO实际上将用于数据而不仅仅是屏幕规格,则应该使用额外的映射。
我还从我的WCF层简单地返回实体,让客户端上自动生成的代理对象成为DTO。由于代理类,实体几乎变成了DTO,并且没有业务逻辑传输到客户端。
当然,这都取决于您的架构目标。在我看来,这个问题有点主观和争议性。

1

我喜欢在MVC项目中定义DTO,然后创建扩展方法来从领域实体转换为DTO(反之亦然)。

转换将在mvc函数中进行。


0

发布的链接跳转到垃圾页面了,请更新一下,好吗? - Ayyappa

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