2011-05-05 69 views
6

我们正在使用EF,WCF和jQuery实现SOA Web应用程序。在SOA应用程序中使用DTO的最佳方式是什么?

这里是我们在一个简短的视图结构:

------------- --- 
| UI  | | | 
------------- | | 
| Services | | D | 
------------- | T | 
| Businsess | | O | 
------------- | | 
| Dal | | | 
------------- --- 

我们知道,我们应该有DTO类专门的服务和用户界面之间传递层之间的数据,但我们必须对这样一些概念问题使用DTO(发送到UI或从UI接收)。

对于数据驱动项目,我们可以使用POCO自动生成DTO对象。但在大型应用中并不那么简单。

我们知道两种解决方案来解决我们的问题:

第一溶液(使用POCO除了新手动创建的DTO)

例如,假设我们有许多领域的实体。还有一个显示实体记录的查找组合框。我们只需要一个实体键作为组合框值字段,另一个字段(例如标题)作为组合框文本字段。所以我们创建一个名为“GetAllItemsTitle”的方法来检索所有实体。现在我们应该返回我们想要的结构(在这个例子中是一个键和一个值)。所以我们必须创建一个新类来存储该结构(一个键和一个值)。

这将是新的DTO类:

[DataContract] 
public class SampleManuallyDto 
{ 
    [DataMember] 
    public long Id { get; set; } 

    [DataMember] 
    public string Title { get; set; } 
} 

和方法签名是这样的:

public List<SampleManuallyDto> GetAllItemsTitle() 

(使用可空或Emptyable的DTO)解决方案二

我们可以绕过POCO并手动创建DTO。然后,我们可以将DTO的所有属性定义为可空或类似可以被识别为空(我称之为可清空)的属性。它允许我们为几个目的使用DTO。当然,我们需要遵循适配器模式。例如,为那些名为“FromEntity”和“ToEntity”的可清空DTO创建两个方法,将我们手动创建的DTO转换为实体框架的EntityObjects。

现在我们可以在“第一个解决方案”(GetAllItemsTitle)的例子中绕过创建新的DTO类。

方法签名会是这样:

public List<SampleDTO> GetAllItemsTitle() 

但在方法体中,我们只需填写“ID”和“标题” SampleDTO的性能。正如我所说的,SampleDTO的所有属性都可以是空的,所以我们只填充我们想要的并将其他空置空。

结论

通常,第一溶液(使用POCO除了新手动创建的DTO)是Strongy类型的。只需查看方法签名(没有额外的属性)就可以找出每种方法的返回数据类型。但我们担心管理手动创建的DTO。他们很快就会长大。

但第二种解决方案是一种更加动态的方式,并且唯一能够识别将从“GetAllItemsTitle”返回的内容的方法是查看方法主体或其文档。所以我们担心“运行时错误”。开发人员可能会认为一个属性在空时不应该为空。

此外,我们面对这样的问题,当从用户界面“屏蔽”数据到服务时所面临的例子。例如用于更新和插入等操作。即使是关于“搜索标准”,我们也有相同的选择。

对不起,长期以来的问题。 请帮助我们提供友善的建议。

回答

2

忘记所有关于数据层。创建适用于每个特定Web服务调用的DTO:s。

如何构建DTO或如何使用它并不重要。唯一重要的是他们是如何设计的,以最大限度地减少每个操作的Web服务调用量。

例如:假设您有一个用例,您需要遍历所有用户以修改其地址。如果您首先需要获取所有用户,然后针对每个用户进行web服务调用以获取其地址,则糟糕的设计会是。一个合适的设计是在一次调用中返回一个UserWithAddress DTO的列表。

+0

不错的主意,我们会关心它。但是现在我们推荐哪一种解决方案?当然,我认为我们应该允许自己创建尽可能多的DTO。对? – 2011-05-05 14:06:41

+0

从构建服务API开始。所需DTO的数量应该在此过程中出现。 – jgauffin 2011-05-05 14:18:06

+0

我不知道你是否对你的对象感到尴尬,但总的来说,它总是一个很好的做法来看看存在的东西。你的DTO实际上和Dictionary对象的NameValuePair是一样的。 – 2012-05-24 07:12:39

1

那么我们如何管理大型项目的大量DTO呢?你的意思是我们应该为UserInfo的每个组合都有一个DTO,比如UserWithAddress,UserWithAddressAndAge,UserWithAge,UserWithPhoneNumber,UserWithBlahBlahBlah?这在大的领域会很混乱,很难管理和维护。我非常喜欢Nullable DTO。 对于从现实世界映射的每个对象,您应该有一个Dto。这是指定应如何使用的业务责任。一旦你创建了一个Dto,然后根据你的业务使用它。调用GetUserAddress服务,并且不要期望UserAge或任何其他事情。当我们将用户映射到我们的设计中的面向对象的用户时,用户就有一个DTO。

还有一件事!如果我们为每个单一目的和数据服务的组合都创建一个Dto,作为最近加入到支持团队的开发人员,如何为我的新方法找到所需的Dto?我应该搜索所有的Dtos,并小心我的正确选择(如果我是一个懒惰和粗心的开发者,会发生什么?)也许我应该阅读一本像“The DTOS OF THE PROJECT!”这样的文档书。熟悉可用的DTO。

1

DTOs应根据需要映射到请求或能力。您可以聚合各种基础数据实体并返回合成或类似外观的DTO,也可以返回仅代表单个数据实体的一部分的贫血DTO。在做出此决定时,您希望平衡有效负载,粒度和其他SOA关注点。

http://www.soapatterns.org/entity_abstraction.php