验证功能应该直接访问存储库吗?

时间:2013-04-03 14:11:23

标签: validation orm domain-driven-design ddd-repositories

我的申请表中有以下内容: Action Orm实体(来自telerik开放访问) 存储库(动作) AppService(保存存储库的实例)

当我需要保存实例时,我将实例发送到AppService。然后,AppService调用验证器来验证要保存的实例。验证器基于http://codeinsanity.com/archive/2008/12/02/a-framework-for-validation-and-business-rules.aspxhttps://github.com/riteshrao/ncommon上的完整代码)

基本上我在AppService中的保存功能看起来像这个

Public Sub AddAction(ByVal Item As Data.Model.Action)
        Contract.Requires(Of ArgumentNullException)(Item IsNot Nothing, "Item is nothing.")

        Dim validateResult As Rules.ValidationResult = _ActionValidator.Validate(Item)
        If Not validateResult.IsValid Then
            Throw New Validation.ValidationException(validateResult)
        End If

        Try
            _ActionRepository.Add(Item)
            _unitOfWork.SaveChanges()
        Catch ex As Exception
            _unitOfWork.ClearChanges()
            Throw New DataServiceException(ex.Message, ex)
        End Try

    End Sub

用于检查Action项的属性,示例代码非常有效。我的问题开始时,我需要确保相同的操作没有两次添加到同一客户的数据库(即.ID是差异,名称是相同的,客户是相同的)

我看到它有几个选择: 选项1 :使用

之类的内容检查重复操作
function(validatedItem) item.Customer.Actions.Any(function(item)  item.id<>validatedItem.id andalso item.name=validatedItem.name))

基本上我从保存的动作回到客户然后回到他的所有动作并检查是否存在具有不同id和同名的任何动作

不利方面是:

一个。为了使其工作,当访问项目的客户属性时,从DB读取整个客户对象,在这种情况下冗余是多余的 湾Any客户端正在评估Any函数item.Customer.Actions返回IList(Of Action)

选项2 :让验证类可以访问操作存储库。然后我可以简单地做一些像

这样的事情
'assume I already have validatedItem
repository.Any(function(item) item.id<>validatedItem.id and item.customerid=validatedItem.customerid and item.name=validatedItem.name)

这将导致将Exists查询发送到数据库,但缺点(?)是验证框架不应该直接访问存储库(据我所见,我可以找到的极少数示例中使用验证和ORM)

选项3 :让验证类可以访问AppService并使用AppService检查是否存在重复。 问题: 一个。我创建了一个循环引用(AppService-&gt; Validation Class-&gt; AppService) 湾我需要在AppService中创建许多无用的函数,以便根据仅与验证相关的条件加载项目

任何想法这里最好的课程是什么?

1 个答案:

答案 0 :(得分:2)

最简单的方法是不从您的域中检查数据库中的重复项。

如果实体集合是您聚合的一部分,那么这不是问题,因为您不允许将副本添加到集合中。由于聚合作为一个整体存储,你永远不会遇到问题。

对于您不希望重复的情况,例如电子邮件地址,并且没有实体集合由聚合表示(例如系统中的Users),您可以让数据库强制执行独特性。只需拿起例外并报告回来。在许多情况下,您的验证将无法强制执行唯一性,因为它没有/实现数据库系统所需的锁定。

所以我只需将 放到数据库中。