title: Validating unique values in a domain entity
body: <p>I have a scenario where a domain entity property needs to be verified to be unique before it can be saved to the database. Here is a simple <em>Product</em> class. Let's assume I want to validate that when creating a new Product that the <strong>ProductKey string property is unique</strong>:</p>
  
  <pre><code>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;
          }
      }
  }
  </code></pre>
  
  <p>Since I'm using Domain Driven design the Product entity has no knowledge of persistence or the service layers. I could just add a check to the Service method as follows:</p>
  
  <pre><code>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;
      }
  
  }
  </code></pre>
  
  <p>This is simple enough but ideally I would like such logic to live in the domain model. Perhaps by raising some kind of validation event that can be caught by the service layer?</p>
  
  <p>Is there a best practice or known design pattern for this type of scenario? </p>