2012-12-17 55 views
1

我有一個場域實體屬性需要驗證爲唯一,然後才能保存到數據庫。這裏有一個簡單的產品類。假設我想驗證創建一個新的產品,該的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; 
     } 
    } 
} 

由於我使用的領域驅動設計的產品實體沒有持續性或服務層的知識。我只需要添加一個檢查服務方法如下:

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; 
    } 

} 

這是很簡單,但我非常希望這樣的邏輯住在域模型。也許通過提高可以被服務層捕獲的某種驗證事件?

這種類型的場景是否有最佳做法或已知設計模式?

+0

您不應該爲公共設置者重要或依賴於其他屬性的屬性。如果這樣做,實體可以隨時將其設置爲不一致的狀態。在這裏閱讀:http://blog.gauffin.org/2012/06/protect-your-data/ – jgauffin

+0

當然,但這只是一個簡單的例子來表達我的問題。在這種情況下,如何讓財產製定者私下幫助我?然後,我是否會將數據訪問問題添加到我的域模型中? –

+0

我不能假設你不這樣做,在DDD。我所看到的只是一個打破域實體封裝的例子。但由於它不回答問題,我只是留下了一條評論。 – jgauffin

回答

4

產品密鑰唯一性不是域對象知識。所以你不需要域驗證。爲什麼產品應該關心關鍵唯一性?在我看來,這是一個應用層的責任。你的解決方案對我來說似乎是有效的。

+0

同意。檢查存儲庫的唯一性以及可能的數據庫約束是解決這類問題的一般方法。 – eulerfx

+1

但是,密鑰的格式可能是域特定的。在設置密鑰時,應在域實體內使用這種驗證。 – jgauffin

+0

@jgauffin是的,好點。這是'域驗證'發揮作用的地方。 – masted

1

對於併發事務,您的解決方案不安全,除非使用可序列化的隔離級別。我寧願使用更簡單的解決方案。執行此操作的常用方法是僅在數據庫中使用唯一約束。試圖在您的域中對此進行建模只會導致不必要的複雜性。

+0

我確實在數據庫級有一個約束來充當不可逾越的障礙,我只是試圖在更高級別上捕獲它,並以比通過圖層將異常向上冒泡的更優雅的方式進行處理。您提出了關於併發性的優點! –