如何在 UI、BLL、DAL 之间使用 DTO

Posted

技术标签:

【中文标题】如何在 UI、BLL、DAL 之间使用 DTO【英文标题】:How to use DTO's between UI, BLL, DAL 【发布时间】:2011-06-09 02:57:53 【问题描述】:

我正在尝试编写一个小应用程序,在 BLL 和 DAL 之间有非常严格的界限,现在我想知道在层之间传递数据(域传输对象)的最佳方式是什么。

我在 BLL 和 DAL 都可以访问的域级别(类库)中实现了一些类。这些类基本上只包含属性/数据成员,目前反映 DAL 数据。例如:

class CustomerData

  // some data fields

然后我在 BLL 中实现了一些类:

class Customer : CustomerData

  // Some methods

在我的 DAL 中,我通过 Linq-to-Sql 从数据库中获取客户记录。然后我通过以下方式将 linq 对象映射到我的 Domain 对象:

CustomerData.field = LinqObject.field
// Etc

因此,我的想法是,当请求时,我现在从我的 DAL 到 BLL 的 CustomerData 实例(并且我应该将 Customer 实例传递给我的 UI)。

因此,在我的 BLL 中,我将收到一个 CustomerData 实例,但现在我想从中创建一个 Customer。

问题:

    现在我是否必须在我的 BLL 中创建一个客户实例并再次复制所有字段成员? 客户 c = 新客户; c.field = CustomerData.field; 如何在没有字段复制步骤的情况下从 CustomerData 创建客户? 我是否应该使用组合? 类客户 客户数据数据; 在我当前的布局中是否有更有效的方法(更少的编码等)来做到这一点? 有更好的方法吗? 一般有什么 cmets 吗?

谢谢!

【问题讨论】:

Yorah 对 #1 的回答 +8。像这样的猴子编码对你来说可能看起来很痛苦。最后,它实际上是错误的做法,因为它会增加错误并使事情变得如此痛苦。也试试 ValuInjector - 许多人比 AutoMapper 更喜欢它,更轻量级。请务必重复使用您的映射。 【参考方案1】:

通常我认为 DTO 不是特定于层的,由 DAL 创建/使用,由 BLL 处理并由 UI 使用/创建。

通常每一层都是VS解决方案文件夹中的一个单独项目,因此DTO是每一层引用的另一个项目。

这样,如果有一个字段需要在 UI 中存在,但在其他层中不存在,则可以继承 DTO。

【讨论】:

【参考方案2】:

从我的角度来看一些笔记,我不是神谕,但希望它能提供一些帮助:)

对我来说,这里的“模型”太多了。它可能会引起混淆并导致大量代码只是为了在不同的表示之间复制数据。大量的代码意味着更多的错误。然后,我认为在定义业务类时,您的数据类和业务类之间的继承会限制您。如果你想创建一个由多个数据类组成的业务类呢?我认为你应该使用接口或组合。

通常,我只使用一个反映业务领域的概念模型。正如 Dead Rabit 所指出的,这个模型被数据和业务层使用,在某些情况下甚至是表示层(在较小的应用程序中)。对于持久性,我使用 O/RM,例如 EF 4。

对于较大的项目,尤其是在分布式场景中,我将自定义 DTO 用于 UI 层。这些类反映了 UI 的需求,并且可能与概念模型中的实体有很大不同。

就个人而言,我认为 Entity Framework 4 在根据这种结构构建应用程序时对您有很大帮助,如果您处于项目的早期阶段并使用 .NET 4,您可能想看看吗?

    是的,您可能需要这样做。 使用组合 是的,我会使用合成 以 Entity Framework 4 为例 (-"-) 见上文

【讨论】:

肯定会检查 EF4。我最初的判断也是这个应用程序的层太多。但是过去我的层总是“泄漏”太多,所以我在这里对自己严格要求。【参考方案3】:

如果您坚持在 DTO 上设置多个层,您可以使用 AutoMapper 帮助您在一行代码中从一层转换到另一层(在 DTO 中使用相同的约定)。

CustomerData customerData = Mapper.Map<LinqObject, CustomerData>(linqObjectInstance);

您还应该查看 PresentationModel 模式:http://martinfowler.com/eaaDev/PresentationModel.html

如果你想走这条路,你也可以google for MVVM (Model-View-ViewModel)。

【讨论】:

【参考方案4】:

您没有完全使用 DTO 的 .在您的 Customer 类中,将 CustomerData 直接返回到您的 UI。

并且不需要从CustomerData继承Customer

编辑: 我在这里完全使用了这个词,因为 CustomerData 是 DTO,所以不要返回 Customer,而是返回 CustomerData,因为它是您的 DTO,如下图所示。

一个建议,你应该使用Repository Pattern 来隔离你的 BLL 和 DAL。

1]

【讨论】:

我将如何“充分利用” DTO 的? 有人给我一篇文章,其中有一个很好的例子来说明 DTO 以及 BLL 和 DAL 之间的交互,这不是贫血的域模型反模式吗?这让我很困惑

以上是关于如何在 UI、BLL、DAL 之间使用 DTO的主要内容,如果未能解决你的问题,请参考以下文章

业务层 (BLL) 数据访问层 (DAL) 和 UI 之间的通用结构?

使用 LINQ 作为 DAL 时如何传输数据?

不同的 UI 共享相同的 BLL 和 DAL

使用 DTO 在服务层和 UI 层之间传输数据

除了实例化 DAL 的 BLL 之外,还有啥选项允许在 n 层解决方案中进行单元测试,而不会将 DAL 暴露给 UI 或将 BLL 暴露给 DAL?

GUI、BLL 或 DTO 中的 JSON/XML 输出?