【问题标题】:Managing DTOs and mapping in large .NET project在大型 .NET 项目中管理 DTO 和映射
【发布时间】:2011-09-29 21:32:51
【问题描述】:

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

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

管理我们所有的 DTO 和映射已经变得非常痛苦。目前,发送要存储在数据库中的联系人如下所示:

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

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

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

【问题讨论】:

    标签: .net mapping dto


    【解决方案1】:

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

    请问您为什么觉得需要同时拥有 ContactDTO 和服务联系人?你不能只是传递服务联系人吗?我知道这不是最佳做法,但它可能会使您免于 RSI

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

    【讨论】:

      【解决方案2】:

      我经常遇到这种情况,但就我而言,我选择接受它,因为使用 DTO 的决定是有意的 - 我想要我的服务、客户端、代理、和合同程序集被彻底分离。

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

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

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

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

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

      【讨论】:

        【解决方案3】:

        加快流程的一些事项需要考虑:

        我编写了一个代码生成器,您可以从数据库中选择表和列并让它生成一个 C# DTO。这节省了大量不必要的输入,并且可以更快地生成 DTO。提前一点时间,但是当您有一个包含 20 列的表格时,您需要进行映射,这会有所帮助。

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

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-01
          • 2021-10-28
          • 1970-01-01
          • 1970-01-01
          • 2012-02-13
          相关资源
          最近更新 更多