领域模型验证:如何以及在哪里进行验证

5
一个典型的EF+MVC系统将有两个或三个级别的验证:
  1. 针对ViewModel:输入/物理验证(DataAnnotations,FluentValidation),换句话说,长度,空值,范围,正则表达式等。
  2. 针对Model:输入/物理验证(重复步骤一,如果没有使用MVC并且数据来自另一个系统,WCF,表单等)
  3. 针对Model:逻辑/“业务规则”验证
我找不到关于2+3实际Model /实体/域/“业务规则”的最佳验证做法。 我们要么:
  • 在实体的属性设置器中放入简单的验证规则(但这真的很混乱)
  • 挂钩EF的SaveChanges(),如果实体处于AddedModified状态,则触发验证(这将同时验证整个实体)
这很难维护。 ViewModel验证考虑得很多,但对于Model验证而言,它是特定于领域的,所以需要您确定创造性的解决方案,我的不太好。
  • 是否有更好的方法或有用的工具(例如,DataAnnotations或FluentValidation,但用于域实体)?
  • 模型验证的最佳位置或触发模型验证的最佳位置在哪里?

我的问题并不特别关注客户端/服务器。1 表示验证输入:null/长度/范围等。然后 2 是同样的事情,但如果数据来自 WCF 或另一个系统,那么 1 就不会发生,所以您需要再次执行输入/物理验证以确保安全。忽略所有这些,我真正需要了解的是人们如何为域执行 2+3。 - Bobby B
1
你的前提是错误的,因此基于那个前提的问题也是错误的。MVC不为模型提供任何验证,它只为视图模型提供验证。EF为数据模型提供验证。业务层或领域模型在EF或MVC之外,并且完全由您控制如何进行验证。 - Erik Funkenbusch
我们正在争论语义,但如果您删除冒犯性词语“逻辑”,那么问题仍然存在。对模型进行验证(可能使用逻辑/业务规则)并不像为ViewModel进行验证那样直截了当。 - Bobby B
真相。但是直到他们使用面向方面编程、DataAnnotations以及像FluentValidator这样的工具,人们才会这么说。我正在寻找一种更好的方法。如果还没有(这样的方法),那么作为答案也可以。 - Bobby B
1
没有任何阻止你在业务逻辑中使用FluentValidation。 - Erik Funkenbusch
显示剩余4条评论
1个回答

6
一个典型的MVC+EF系统将有3个层,但这不是你所讨论的。
1.演示层(输入/输出) 2.业务层(逻辑层) 3.数据层(模型代表低级数据)
MVC为第一层提供验证。 EF为第三层提供验证。 无论是MVC还是EF都没有为第二层提供验证功能。 如果您想在那里进行验证,必须自己操作或使用第三方业务对象框架。
第1层和第3层的验证是分开的,即使在许多情况下它们可能具有相似的验证。 原因是验证是通过不同方式实现的,并且具有不同的要求。
例如,您的数据库中可能有一个可为空的字段,出于数据建模或业务逻辑原因(假设某些数据已预加载,并且用户需要更新该字段作为业务过程的一部分)。 数据层说它是可空的,但您希望UI使其成为必填项。
简而言之,数据模型不应强制执行业务规则。 因此,除了针对物理数据模型进行验证(即,如果字段可以为空,则模型中的数据类型应为空,否则不应为空),您不需要在数据模型中进行任何验证。 在大多数情况下,您无法插入无效(从数据模型的角度来看)的数据,因为代码模型不允许这样做。 唯一的例外是字符串变量,它们显然可能超出物理模型的大小限制,但如果发生这种情况,则会抛出异常。
您的中间层,业务层,应该是您需要验证业务规则的地方(例如,客户采购订单必须以字母开头)。 MVC或Entity Framework,或WCF或任何其他框架都没有提供任何验证的方法。
存在一些不协调之处,因为业务规则应该(在理论上)驱动演示层验证。 但是,MVC没有内置功能来执行此操作。 因此,您最终会在UI中复制业务规则。
至少有一个第三方业务对象框架试图解决这个问题。 CSLA。 他们提供了一个自定义的MVC模型绑定器,将业务对象与UI联系起来进行验证,但这只是使用MVC的内置可扩展性来实现的。
因此,如果您不想使用专用的业务对象框架,则要么在UI和业务层之间复制验证,要么尝试找出自己的方法来控制UI验证的业务层。

正如我在上面的评论中提到的,这个问题并不是关于MVC的。它被引入来解释MVC对ViewModels的验证设计得非常好,而且优雅而几乎自动化。我希望我们的领域或M在MVC中也能有同样的效果。 - Bobby B
@BobbyB - 我仍然不明白你想要什么。实体代码模型将不允许您插入格式错误的内容,不会允许您在非空字段中插入null,不会允许您在数字字段中插入字符,也不会允许您插入无效日期等等。当您设法通过一些漏洞(例如,超出或低于日期精度)时,它将抛出异常。尝试插入比字段容量更多的字符或其他任何操作都是一样的。 - Erik Funkenbusch
再次强调,中间业务/领域层与MVC或EF无关。该框架不提供在此方面进行验证的功能,因此需要自己完成。 - Erik Funkenbusch
是的,我在询问逻辑业务规则。如果日期是公共假日,则业务关闭,只允许下一个工作日等。我解释说没有内置的方法来实现这一点,我的问题是其他人是如何做到的以及在哪里做到的。我们通过属性设置器和拦截SaveChanges来实现它。是否有更好的方法或工具。这个问题非常简单。 - Bobby B
@garfbradaz 同意Mystere Man的观点,仓储模式(通常)位于数据之上,但不包括业务规则(即与数据本身无关,而是与数据在逻辑上代表的内容有关的规则)。我们使用它们,但我想知道业务逻辑和相关验证将发生在哪里。 - Bobby B
显示剩余11条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接