我一直在阅读Pro ASP.NET MVC框架,Steven Sanderson,在第11章中讨论了数据验证。
在页390,我们看到将验证逻辑移动到模型层部分。在本节中,我们将在第392页中看到一些代码,说明如何实现验证。
代码实现了GetRuleViolations()
方法,如果某些内容不正确,Save()
方法会使用它来抛出RuleException
。
然而,在我看来,域名和数据访问层之间没有区别,这里是代码:
public void Save() {
var errors = GetRuleViolations();
if (errors.Count > 0)
throw new RuleException(errors);
// Todo: Now actually save to the database or whatever
}
private NameValueCollection GetRuleViolations() {
// validations...
}
在我正在工作的项目中,我有一个域层,尽可能地保持持久性,以及数据访问层,通过NHibernate实现数据访问,并实现在域层中定义接口的存储库。
如果我按照作者在此提出的那样实现验证规则,在“Save()
”方法中,它们将继续我的数据访问层,但至少我认为,它们应该驻留在域模型上!
所以,我的问题是:创建分层应用时,域层实现域实体并将接口暴露给存储库(持久性无知),数据访问层从域层实现存储库并实现所有数据访问代码, 验证规则应驻留在哪里 ?
我的主要(或至少第一个)接口将是一个ASP.NET MVC应用程序,如果这可能会改变任何内容。
感谢。
答案 0 :(得分:2)
在MVC架构中,M(模型)包括 域层和数据访问层。所以桑德森的例子并没有错。
也就是说,当您使用这两个层(而不是只有一个)实现域模型时,验证逻辑应该转到域层以增加域对象的内聚力并避免验证逻辑在许多地方重复(例如在每个具体的存储库中)。
答案 1 :(得分:1)
它们绝对属于您的域层(您可以在其中实现IDataErrorInfo
,但这只对我认为的Windows窗体或WPF应用程序有用。)
看起来这个验证哲学与Paul Stovell公开的验证哲学非常相似(查看this article of his)。它非常强大,我经常使用它。基本上:
- 拥有无效的业务对象没有任何问题,只要您不试图坚持它。
- 应该可以从业务对象中检索任何和所有损坏的规则,以便数据绑定以及您自己的代码可以查看是否存在错误并对其进行适当处理。
醇>
因此,由于 Domain Layer 的持久性非常重要,我相信您的实体至少应该知道它们何时被持久化。 Save
方法是一种让他们对自己的持久性负责的方法(他们随后可以委托给数据访问层)。我看不出有什么不妥。
答案 2 :(得分:0)
我通常喜欢始终有效的域对象。 域对象只能通过防止对象变为无效的方法进行更改。
另一方面,表示对象可以包含临时无效值或无法正确解析的值。但是,当数据有效时,方法调用将仅由表示层发布给域对象。
域对象强制执行不变量,表示对象向用户指示应如何修改其输入以尊重约束。
答案 3 :(得分:0)
验证应在您的域层中完成。您的业务逻辑是域的一部分,而不是数据访问。验证可能不在域对象本身(实际的类)内部完成,但它应该存在于域层内。