领域实体、DTO 和视图模型

Posted

技术标签:

【中文标题】领域实体、DTO 和视图模型【英文标题】:Domain Entities, DTO, and View Models 【发布时间】:2011-07-16 20:31:25 【问题描述】:

我有一个带有 POCO 域模型和 NHibernate 存储库层的 ASP.NET MVC 2 应用程序。我的域模型不知道我的视图模型,所以我使用自动映射器从视图模型转到实体,反之亦然。

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

阅读后,我发现强烈建议您不要在域项目之外公开您的实体,而应该使用 DTO。

我明白其中的原因,但我无法弄清楚如何实现它。

我是否在 ASP.NET MVC 中从 viewmodel 映射到 DTO,通过服务层发送 DTO,并从 DTO 映射到服务层中的实体?我应该在哪里定义我的 DTO?

【问题讨论】:

【参考方案1】:

我喜欢让我的服务层将实体封装在其中,并且只返回/接收 DTO。我将服务合同和 DTO 保存在一个单独的程序集中,MVC 项目和服务实现都参考了该程序集。

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

在 app/mvc 项目中,我有时会变得懒惰,只使用 DTO 作为某些操作的模型(尤其是 CRUDy 操作)。如果我需要投影或类似的东西,那么我将制作一个视图模型并使用自动映射器等在 DTO 和视图模型之间进行转换。

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

【讨论】:

这当然是最适合我的情况的——我没有意识到关于这个问题的争论。我只是发现将我的实体暴露在我的服务层之外让我很伤心 - 但直到我将 WCF 添加到项目中后我才开始遇到这些问题。 我认为,如果您的应用程序不是分布式的(应用程序和服务层之间没有网络间隙),那么问题就小得多了。我看过 MS 文章,他们主张在应用程序的所有层中使用实体。我在“alt.net”类型的文章中也经常看到上面的结构,它对我来说效果更好。它还简化了我对应用程序的思考,服务确实是域的入口点。【参考方案2】:

我将我的 DTO 视为 ViewModel,因为 UI 层(MVC 应用程序)正在请求它们。你可以去 Entity -> DTO -> ViewModel 但我认为如果你的服务的唯一消费者是 MVC 应用程序,那就过度工程了。如果 DTO 以某种方式实际用于数据,而不仅仅是屏幕规范,那么您可能应该使用额外的映射。

我还简单地从我的 WCF 层返回实体,并让客户端上自动生成的代理对象成为 DTO。由于代理类,实体几乎成为 DTO,并且没有业务逻辑传递给客户端。

当然,这完全取决于您的架构目标是什么。这个问题是边缘主观和争论恕我直言。

【讨论】:

【参考方案3】:

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

转换将发生在 mvc 函数中。

【讨论】:

【参考方案4】:

我刚刚写了一篇关于绕过所有这些 DTO DO 转换的方法的帖子。也许你看看http://codeblock.engio.net/?p=17

【讨论】:

发布的链接被带到垃圾邮件页面。可以更新一下吗?

以上是关于领域实体、DTO 和视图模型的主要内容,如果未能解决你的问题,请参考以下文章

转:领域模型中的实体类分为四种类型:VODTODOPO

MVC 3 应用程序中的模型、视图模型、DTO

视图层中的 DTO 或域模型对象?

实体 VS 领域模型 VS 视图模型

Nest JS DTO 和实体模型 JSON 不匹配问题

在 RESTful API 中创建和验证实体模型及其 DTO 的正确方法是啥?