我有一个调用我的WCF业务服务层的Web客户端,后者又调用外部WCF服务来获取实际数据。最初,我认为我会使用DTO并在不同的层次中拥有单独的业务实体......但我发现提倡DTO的微不足道的例子很简单。我看到太多重复的代码并没有太大的好处。
考虑我的域名:
示例域 我有一个单独的UI屏幕(Asp.net MVC View),显示患者的药物清单,不良反应(药物之间)和患者可能患有的任何临床情况(如抑郁或高血压)。我的域名模型从顶层开始:
MedicationRecord
List<MedicationProfile> MedicationProfiles
List<AdverseReactions> Reactions
List<ClinicalConditions> ClinicalConditions
MedicationProfile is itself a complex object
string Name
decimal Dosage
Practitioner prescriber
Practioner is itself a complex object
string FirstName
string LastName
PractionerType PractionerType
PractionerId Id
Address Address
etc.
此外,在发出WCF请求时,我们有一个请求/响应对象,例如
MedicationRecordResponse
MedicationRecord MedicationRecord
List<ClientMessage> Messages
QueryStatus Status
and again, these other objects are complex objects
(and further, complicates matter is that they exist in a different, common shared namespace)
此时,我倾向于MedicationRecordResponse 我的DTO。但是在纯DataContracts和DTO以及设计分离方面,我想这样做吗?
MedicationRecordResponseDto
MedicationRecordDto
List<ClientMessageDto>
QueryStatusDto
and that would mean I then need to do
MedicationProfileDto
PractitionerDto
PractitionerTypeDto
AddressDto
etc.
因为我已经在屏幕上显示了几乎所有信息,所以我实际上为每个域对象创建了1个DTO。
我的问题是 - 你会怎么做?你会继续创建所有这些DTO吗?或者您只是在一个单独的程序集中共享您的域模型?
以下是其他似乎相关的问题的解读:
答案 0 :(得分:7)
看看优秀的文章
以上链接不起作用,看起来像一个域问题(我希望它会被修复),这里是来源:
答案 1 :(得分:3)
我总是厌恶由DTO产生的重复类层次结构。这似乎是对DRY原则的公然违反。但是,经过仔细研究,DTO和相应的一个或多个实体扮演不同的角色。如果您确实应用了域驱动设计,那么您的域实体不仅包含数据,还包含行为。相比之下,DTO仅承载数据并在您的域和WCF之间充当adapter。所有这些在hexagonal architecture也称为端口和适配器以及the onion architecture的上下文中更有意义。您的域是核心,WCF是一个外部公开您的域的端口。 DTO是WCF如何运作的一部分,如果你同意它是一个必要的邪恶,你的问题从尝试消除它们转变为拥抱它们,而是专注于如何促进DTO和域对象之间的映射。一种流行的解决方案是AutoMapper,它减少了您需要编写的样板代码量。除了缺点,DTO还带来了很多好处。一个是它们在域实体和外部世界之间提供缓冲区。这对于重构非常有帮助,因为您可以非常好地封装核心域。另一个好处是,您可以设计您的DTO,使其满足服务使用者的要求,这些要求可能并不总是与您的域对象的形状完全一致。
答案 2 :(得分:3)
就个人而言,我不喜欢使用MessageContract作为实体。不幸的是,我有一个使用MessageContract作为实体的现有WCF服务 - 即数据直接填充到数据访问层中的MessageContract中。没有涉及翻译层。
我有一个使用此服务的现有C#控制台应用程序客户端。现在,我有了新的要求。我需要在实体中添加一个新字段。客户不需要这样做。新字段仅用于服务中的内部计算。我必须在MessageContract中添加一个名为“LDAPUserID”的新属性,它也可以作为一个实体。
这可能会也可能不会破坏客户端,具体取决于客户端是否支持Lax Versioning
。请参阅Service Versioning。
很容易错误地认为添加新成员不会破坏现有客户端。如果您不确定所有客户端都可以处理松散的版本控制,建议使用严格的版本控制指南并将数据协定视为不可变的。
凭借这种经验,我认为将MessageContract用作实体并不好。
另请参阅MSDN - Service Layer Guidelines
设计在业务实体和数据合同之间转换的转换对象。
参考文献: