1

我有一个场景,需要验证域实体属性是唯一的,然后才能将其保存到数据库中。这是一个简单的Product类。假设我想验证在创建新产品时ProductKey 字符串属性是唯一的

public class Product : EntityBase
{
    int ID { get; set; }
    string ProductKey { get; set; }
    int CategoryID { get; set; }

    bool IsValid
    {
        get
        {
            if (string.IsNullOrEmpty(ProductKey))
            {
                ValidationErrors.Add("ProductKey Required.");
            }

            if (CategoryID == 0)
            {
                ValidationErrors.Add("CategoryID Required.");
            }

            /* Validation that the product key is unique could go here? i.e. requires a database read. */

            return ValidationErrors.Count() == 0;
        }
    }
}

由于我使用的是领域驱动设计,因此产品实体不了解持久性或服务层。我可以向 Service 方法添加一个检查,如下所示:

public class ProductService 
{
    private IProductRepository _productRepository = new ProductRepository();

    public int CreateProduct(Product item) 
    {
        if (item.IsValid)
        {
            if (ProductKeyIsUnique(item.ProductKey))
            {
                _productRepository.Add(item);
            }
            else
            {
                throw new DuplicateProductKeyException();
            }

        }
    }

    private bool ProductKeyIsUnique(string productKey)
    {
        return _productRepository.GetByKey(productKey) == null;
    }

}

这很简单,但理想情况下我希望这样的逻辑存在于域模型中。也许通过引发某种可以被服务层捕获的验证事件?

这种场景是否有最佳实践或已知的设计模式?

4

2 回答 2

5

产品密钥唯一性不是领域对象知识。所以你不需要域验证。为什么产品应该关心关键的唯一性?在我看来,这是应用层的责任。您的解决方案似乎对我有效且正确。

于 2012-12-17T15:14:03.897 回答
1

除非您使用可序列化的隔离级别,否则您的解决方案对于并发事务是不安全的。我宁愿使用更简单的解决方案。执行此操作的常用方法是仅在数据库中使用唯一约束。尝试在您的领域中对此进行建模只会引入不必要的复杂性。

于 2012-12-18T08:52:42.427 回答