如何在业务逻辑层中设计数据传输对象

时间:2009-02-22 07:19:43

标签: c# dto llblgenpro business-logic-layer

DTO

我正在构建一个我希望扩展到许多用户的Web应用程序。此外,我需要通过Web服务向受信任的第三方公开功能。

我正在使用LLBLGen生成数据访问层(使用SQL Server 2008)。目标是构建一个业务逻辑层,使Web应用程序不受DAL细节的影响,当然,还要提供超出DAL的额外级别的验证。此外,就我现在所知,Web服务基本上是BLL的薄包装。

当然,DAL有自己的一组实体对象,例如CustomerEntity,ProductEntity等。但是,我不希望表示层直接访问这些对象,因为它们包含DAL特定方法,并且程序集特定于DAL,依此类推。因此,我们的想法是创建数据传输对象(DTO)。我们的想法是,这些本质上是普通的旧C#/ .NET对象,它们拥有CustomerEntity的所有字段,实际上是数据库表Customer,但没有其他东西,除了一些IsChanged / IsDirty属性。所以,会有CustomerDTO,ProductDTO等。我认为这些将继承自基础DTO类。我相信我可以使用LLBLGen的一些模板生成这些,但我还不确定。

因此,想法是BLL将通过接受和返回这些DTO对象来公开其功能。我认为Web服务将处理将这些对象转换为使用它的第三方的XML,许多可能不使用.NET(也有些东西可以通过Web应用程序上的AJAX调用使用JSON调用脚本)。

我不确定设计这个以及如何前进的最佳方式。以下是一些问题:

1)如何将其暴露给客户端(表示层和Web服务代码)

我在想有一个公共类有这些方法,每次调用都是一个原子操作:

InsertDTO,UpdateDTO,DeleteDTO,GetProducts,GetProductByCustomer等等......

然后客户端只调用这些方法并传入适当的参数,通常是DTO。

这是一种好的,可行的方法吗?

2)从这些方法中返回什么?显然,Get / Fetch类方法将返回DTO。但是Inserts呢?签名的一部分可能是:

InsertDTO(DTO dto)

但是,插入什么时应该返回?我希望收到错误通知。但是,我对某些表使用自动增量主键(但是,有些表具有自然键,特别是多对多表)。

我想到的一个选项是Result类:

class Result
{
    public Exception Error {get; set;}
    public DTO AffectedObject {get; set;}
}

因此,在插入时,DTO将获取其get ID(如CustomerDTO.CustomerID)属性集,然后放入此结果对象。如果Result.Error!= null,客户端将知道是否存在错误,然后它将知道Result.AffectedObject属性中的ID。

这是一个好方法吗?一个问题是它似乎传递了大量来回的冗余数据(当它只是ID时)。我不认为添加“int NewID”属性是干净的,因为一些插入不会有这样的自动增量键。另一个问题是我认为Web Services不会很好地处理这个问题吗?我相信他们只会在Result类中返回AffectedObject的基础DTO,而不是派生的DTO。我想我可以通过拥有大量不同类型的Result对象来解决这个问题(可能是从基础Result派生并继承了Error属性)但这看起来不太干净。

好吧,我希望这不是太冗长,但我想说清楚。

2 个答案:

答案 0 :(得分:3)

1:这是一种非常标准的方法,非常适合用于最佳单元可测试方法的“存储库”实现。

2:异常(应该在WCF边界上声明为“fault”,btw)将自动引发。您不需要直接处理它。对于数据 - 有三种常见方法:

  • 在合同上使用ref(不是很漂亮)
  • 返回(更新的)对象 - 即public DTO SomeOperation(DTO item);
  • 仅返回更新的身份信息(主键/时间戳/等)

关于所有这些的一件事是它不需要每个操作使用不同的类型(对比你的Result类,每个DTO都需要复制。

答案 1 :(得分:1)

问题1:您可以将WCF数据合同复合类型视为DTO来解决此问题。这样,您的UI层只能访问DataContract的DataMember属性。您的原子操作将是您的WCF接口公开的方法。

Q2:配置您的响应数据合同以使用您的主键等返回新的自定义类型... WCF也可以配置为将异常冒泡回UI。

相关问题