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

5

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

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

class CustomerData
{
  // some data fields
}

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

class Customer : CustomerData
{
  // Some methods
}

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

CustomerData.field = LinqObject.field
// Etc

我的想法是当需要时,我会从我的数据访问层(DAL)向业务逻辑层(BLL)传递一个CustomerData实例(并且我应该向用户界面(UI)传递一个Customer实例)。
因此,在我的BLL中,我将接收到一个CustomerData实例,但现在我想用它来创建一个Customer。
问题:
1. 我是否必须在我的BLL中创建一个Customer实例,并再次复制所有字段成员? Customer c = new Customer; c.field = CustomerData.field;
2. 如何从CustomerData创建一个Customer而不进行字段复制步骤?
3. 是否应该使用组合? class Customer { CustomerData Data; }
4. 在当前布局中,有没有更有效的方法(较少编码等)来完成这个任务?
5. 有更好的方法吗?
6. 总的评论?
谢谢!

Yorah对#1的回答得分+8。像这样编码可能对你来说只是让人烦恼的。最终,它实际上是错误的,因为它增加了bug的程度,使事情变得非常麻烦。尝试使用ValuInjector-许多人比AutoMapper更喜欢它,而且更轻量级。一定要重复使用你的映射。 - FastAl
4个回答

8

通常我认为DTO不具有特定的层级,由数据访问层创建/消费,业务逻辑层处理并由用户界面层消费/创建。

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

这样,如果需要在用户界面中存在但其他层级中不存在的字段,则可以从DTO继承。


2

以下是我个人的一些笔记,我不是神谕者,但希望能够提供一些帮助 :)

在我看来,您在这里有太多的“模型”。这可能会导致混淆,并导致大量代码仅用于在不同表示之间复制数据。而且,很多代码意味着更多的错误。然后,我认为您的Data类和Business类之间的继承在定义业务类时有些限制。如果您想创建由几个Data类组成的Business类怎么办?我认为您应该使用接口或组合。

通常,我只使用一个概念模型反映业务领域。此模型既由数据层和业务层使用,有时甚至由演示层(在较小的应用程序中)使用,如Dead Rabit所指出的那样。对于持久性,我使用诸如EF 4之类的O / RM。

对于较大的项目,特别是在分布式场景中,我为UI层使用自定义DTO。这些类反映了UI的需求,与概念模型中的实体可能差异很大。

就我个人而言,如果按照这种结构构建应用程序,Entity Framework 4可以帮助您很多,如果您处于项目的早期阶段并使用.NET 4,您可能需要查看它?

  1. 是的,您可能需要。
  2. 使用组合
  3. 是的,我会使用组合
  4. 例如使用Entity Framework 4
  5. (-"-)
  6. 请参见上文

一定会去尝试EF4。我的初步判断也是这个应用程序有太多层了。但是过去我的层总是“泄漏”太多,所以我在这里试图对自己严格要求。 - Oliver

1

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

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

你还应该看一下PresentationModel模式:http://martinfowler.com/eaaDev/PresentationModel.html

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


0

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

而且没有必要从CustomerData继承Customer

编辑: 我在这里使用了“完全”一词,因为CustomerData是DTO,所以应该返回CustomerData而不是Customer,正如下图所示。

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

DTO1]


我该如何“充分利用”DTO? - Oliver
2
有人能给我一篇文章,用一个好的例子来说明DTO以及BLL和DAL之间的交互吗?这不是贫血领域模型反模式吗?这让我感到困惑。 - Costa

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