Sar*_*esh 12 c# nhibernate validation wcf domain-driven-design
我有一个WCF层,我的域模型在这个WCF层后面.我使用Nhibernate作为ORM工具,我所有的业务逻辑/数据访问等都将在这个WCF层之后.
我向我的客户揭露了DTO.我有以下问题
1)我应该创建DTO吗?将实体直接暴露给wcf客户端有什么害处,因为我的实体也会有业务逻辑方法这样做我不得不用WCF属性来破坏我的权利对象,我觉得这样做不好?
2)如果我公开DTO,我应该验证DTO以及实体.如果我只验证DTO,那么我没有为我的Enitity对象提供任何输入验证.这个可以吗?
3)我应该考虑使用Schema验证在Application Service层(WCF层)中验证DTO吗?或应该使用在文章[博客]给出IValidator方法:http://lostechies.com/jimmybogard/2007/10/24/entity-validation-with-visitors-and-extension-methods/如图麦博加德
有时DTO对我来说似乎是多余的,但我可以使用它来从一个或多个实体中获取详细信息.
我将暴露该服务以各种客户端,因此我的DTO将从一些基地DTO具有凭证细节我将我的实际WCF方法调用(可能使用IEndpointBehaviour和IParamInspector)之前检查每个传入请求来导出
基于响应,我现在同意保留DTO层,这是一个例子,以便场景变得更加明确
假设我在我的WCF应用程序服务层中接受CustomerDetailsDTO的CreateCustomer方法可以由MVC应用程序调用.有一些输入验证,如
输入验证:
i)Name length should be greater than 2 but less than 50 ii) Age is mandatory and cann not be less than 18 (Different other field validations)etc
业务验证:
There could then be some business rules to check for dupliate customer
based on say email or some other factor whcih i think should be part of
my Domain business logic and should reside in CustomerEntity class.
输入验证应该仅应用于服务接口层,因为我们从客户端获取DTO,或者它也应该应用于CustomerEntity
1)我应该创建DTO吗?将实体直接暴露给wcf客户端有什么害处,因为我的实体也会有业务逻辑方法这样做我不得不用WCF属性来破坏我的权利对象,我觉得这样做不好?
是的,SOA需要数据合同.
它们可以或多或少地形式化(CSV,JSON,XSD,WSDL,WADL甚至HTML或txt文件),但如果您无法就此类合同找到协议,则不应采用任何"服务"技术或技术(也没有任何其他IPC的重要性).
远程处理是唯一试图避免此类要求的技术.这是一个惊人的想法,抽象,但具体来说它没有用.
2)如果我公开DTO,我应该验证DTO以及实体.如果我只验证DTO,那么我没有为我的Enitity对象提供任何输入验证.这个可以吗?
您应该验证"合同",而不是业务规则.
例如,WCF DTO可能需要填充一些字段,我将ArgumentNullException在构造函数中使用.
但是你应该记住,DTO用于传输数据.如果您有一个数字字段,由于某些奇怪的原因必须作为字符串传输,您可以验证它,例如阻止DTO的初始化.
3)我应该考虑使用Schema验证在Application Service层(WCF层)中验证DTO吗?或应该使用在文章[博客]给出IValidator方法:http://lostechies.com/jimmybogard/2007/10/24/entity-validation-with-visitors-and-extension-methods/如图麦博加德
如果您需要域模型(这意味着您需要聘请专家来了解应用程序的目的),它必须是唯一负责业务规则的人.因此,对于简单的验证,您不需要任何验证框架.
您需要的是表达性异常,可以轻松映射到正确定义的故障.
编辑以回答新问题
在WCF中,我经常在DTO构造函数中使用输入验证,因此客户端无法发送"无效请求".这具有许多优点,例如,客户端不能使用无效输入来配置DOS攻击.此外,如果您拥有大量客户端,这可以减少网络负载,并使用户体验更好一点,因为他不需要等待服务器响应就知道他忘记了电子邮件字段中的@.
但实际上,年龄超过18岁是一个商业规则,而不是输入规则.
输入规则可以是:"Age字段必须大于Zero",因为负年龄是不可能的,零年龄声音太像用户错误(并且它是int32默认值).
但合同验证还不够.
如果年龄在您的域中是相关的,您将有一个Age结构,包装UInt32(因此之前的输入规则).为什么要换一个UInt32?例如,因为在您的域模型中,您知道两个用户年龄的总和没有意义.
是的,你最多检查一次该号码(一个在客户端,两个在服务器上),但这是正确的,这里.DTO可以独立于域模型发展,域模型不会冒出意外行为的风险(或者根本不需要域模型).
要了解业务规则,请考虑跟踪某种特殊治疗方法的医疗记录应用程序:该命令 void Prescribe(Age patientAge, AntibioticPrescription prescription)可以检查PatientAge参数是否大于之前处方的年龄.这是一个商业规则.另一项业务规则应检查当前处方与前一处方之间的危险交互.
如果是这样,该命令应记录并抛出 3个异常:
ArgumentNullException,处方为空时(假设它是参考类型)InconsistentAge,当患者年龄低于最后一个时MortalPrescription,当这样的处方可以杀死病人.这些异常表达了业务规则的前提条件(除了参数null,当程序员引入某种错误时,它会尽快失败).
| 归档时间: |
|
| 查看次数: |
5591 次 |
| 最近记录: |