在大型.NET项目中管理DTO和映射

时间:2011-07-06 18:53:03

标签: .net mapping dto

我和我的团队正在构建一个大型的.NET WinForms应用程序。该应用程序使用各种“服务”来从我们的数据库中获取数据。每个“服务”都存在于自己的解决方案中,并处理特定类型的数据。因此,例如,我们的“ContactsService”管理检索/保存联系人到我们的数据库。

通常,我们一直在为每项服务构建DTO。因此,我们可能会有一个“ContactDTO”,它对联系人的每个数据都有简单的字符串属性。现在,我们还有一个业务层“Contact”类,它具有完全相同的属性,可能还有一些带有一些业务逻辑的额外方法。最重要的是,“ContactsService”有自己的Contact类,它来自ContactDTO。

管理我们所有的DTO和映射已经成为一件巨大的痛苦。目前,发送要存储在数据库中的联系人如下所示:

  • 地图客户联系至ContactDTO
  • 将ContactDTO映射到服务联系
  • 保存联系
  • 地图服务联系ContactDTO
  • 将ContactDTO映射到客户联系

这只是感觉很糟糕。如果我们向客户端Contact类添加一个属性,我们必须在3-4个地方添加属性和映射。

我们做错了什么,我们怎样才能让生活更轻松?使用像Json.NET这样的东西并拥有JSON DTO会更简单吗?我们检查了AutoMapper,但是一些团队成员认为它太复杂了。

3 个答案:

答案 0 :(得分:2)

我遇到了很多,但在我的情况下,我选择接受它,因为决定使用DTO是故意的 - 我想要我的服务,客户端,代理,和合同组件要干净利落地分开。

使用WCF时,我喜欢的布局是这样的(使用您的联系示例):

  • 客户端程序集
    • 联系(具有客户特征)
  • 共享合同大会
    • 联系(商定的共同DTO)
  • 代理程序集
    • 使用共享合同程序集中的联系人
  • 服务组装
    • 联系人(具有服务业务逻辑特征,例如,这可能是由实体框架等ORM层公开的类型)

我现在正在分享服务和客户之间的合同。如果我需要独立地对它们进行版本化,那么我可以复制共享的Contracts程序集并重新定位Proxy程序集以使用该副本,然后单独修改两个Contracts程序集。但在我工作的大多数情况下,我拥有客户端和服务,所以在两者之间共享Contracts程序集很方便。

当你做出使用DTO隔离组件的架构决策时,这是我能想到的唯一优化,至少不使用代码生成工具(我不知道任何好的,但不必看进入他们)。

编辑:当不使用WCF时,您显然不需要“代理”程序集。

答案 1 :(得分:0)

AutoMapper并不是特别复杂。如果您遵守惯例,例如Contact.Address1成为DTO上的ContactAddress1,除了调用Mapper.Map之外,您不必编写太多代码。或者,您可以使用代码生成,但管理更改仍然很棘手。

我可以问为什么您认为需要同时拥有ContactDTO和服务联系人?你能不能只是通过服务联系?我知道这不是最好的做法,但它可能会让你免于RSI

编辑:忽略我的最后一点 - 由于某种原因,我认为你将服务联系人映射到数据库实体,如NHibernate / Entity Framework

答案 2 :(得分:0)

加快要考虑的过程的一些事情:

我编写了一个代码生成器,您可以从数据库中选择表和列,并让它生成C#DTO。这节省了大量不必要的打字,并且可以更快地生成DTO。前面一点时间,但是当你有一个需要绘制20个列的表时,它会有所帮助。

我还编写了代码生成器来将DTO映射到存储过程以进行保存,删除和查询操作。再节省时间,因为他们中的很多人最终都非常相似。如果您编写了大量繁琐的“咕噜”代码,请考虑使用代码生成器来执行此操作。

使用实体框架或ORM映射器作为后端。这可以节省大量时间,但您必须投资ORM知识并了解其工作原理。

创建从客户端到数据库使用的一组通用DTO。在某些情况下,当您需要客户端的代理或较小的DTO时,这可能不实用,但您可以尝试将一些从客户端传递回服务器的常见DTO。

删除一些图层。我知道这听起来有点反模式,但在某些情况下,洋葱不必太厚。