DDD – 如何针对数据库实施验证

M. *_*och 3 c# validation domain-driven-design ddd-repositories user-defined

我正在努力解决一个基本问题。该项目是用 C# 编写的,但问题很普遍。

我遵循始终有效的对象原则。作为一个示例,我有一个具有强制属性“ProductCategory”的产品实体。允许的产品类别是用户定义的,因此会保留(在数据库中)。

为了类型安全和更好的阅读,我为各种属性定义了值对象来封装这些类型的业务规则。所以就有了一个ProductCategory类。创建 ProductCategory 实例时,工厂方法会检查创建实例之前传递给工厂的字符串的最大长度等。这确保了 ProdcutCategory 的每个实例都是有效的。

简单的参数检查(例如长度)既简单又直接。我的问题是在哪里对可能保留的值实施验证检查。允许值的存储库隐藏了持久性技术,并具有 Exists 或 IsValid 方法。

选项 1)在调用工厂之前从应用程序层调用存储库。

这里,领域层并不像许多人主张的那样依赖于存储库/基础设施层。但工厂无法再确保对象有效。业务规则的实现依赖于应用层。此外,每个需要 ProductCategory 的命令都必须检查存储库,这违反了 DRY。

选项 2)从值对象工厂调用存储库

由于工厂是域层的一部分,因此该层必须能够访问存储库,这会引入额外的耦合。好处是ProductCategory的业务有效性由对象本身保证,无法规避。

是否有其他解决方案可以解决这一困境,或者是否有任何具体标准鼓励其中一种或另一种选择?如果工厂是针对保存在领域层中的存储库接口进行编程并且仅由基础设施层中的存储库实现的,这样可以吗?我试图理解不同的方法,但在这种情况下我感到迷失。

Nei*_*l W 5

如果我理解正确,您的 ProductCategory 值对象会处理其自身的不变量,但特定的 ProductCategory 是否可以分配给特定的 Product 是用户定义的并存储在数据库中。

您可以使用 DomainEvents:

  1. 您将类别分配给域模型中的产品。
  2. 产品添加了一个域事件“ProductCategoryAssigned”。
  3. 在提交工作单元之前,DomainEvent 处理程序会使用数据库检查是否可以将特定类别分配给产品,如果不能,则抛出异常。

这将防止事务以无效状态完成。

您可以使用 ValidatorAggregate:

如果您确实希望您的产品“始终有效”,即使在提交工作单元之前,那么您可以选择:

  1. 创建一个 ValidCategoriesAggregate 和存储库,用于根据产品属性加载有效类别。
  2. 您的产品的“SetCategory”方法(或工厂方法)将 ValidCategoriesAggregate 声明为必需参数,强制您的应用程序层在调用工厂方法之前获取一个。
  3. 在工厂方法中,您可以调用“ValidCategoriesAggregate.HasCategory(category)”,并在创建产品之前抛出异常(如果不存在)。

尽量避免将存储库注入域模型中。