2009-10-04 52 views
16

我已經使用域模型和存儲庫實現了DDD的命令端,但是如何實現查詢端?如何在DDD中實現CQRS的查詢方?

我是否爲UI創建了一個全新的領域模型,以及它保存在項目結構中......在領域層,UI層等中?

另外,我作爲查詢機制使用了什麼,我是否爲UI領域對象,存儲庫以外的東西或其他內容創建了新的存儲庫?

+3

我對面的的Jak查爾頓博客中誰介紹他爲什麼決定不使用DDD查詢在都挺: 「CQS的查詢方不需要強類型的實體,也不需要強類型的DTO - 因爲它主要是臨時數據維護這些實體和DTOs會消耗一個DataTable可以處理的事情的開銷時間不成比例「 http://devlicio.us/blogs/casey/archive/2009/ 06/22/we-are-not-doing-ddd-part-two-cqs.aspx – rohancragg 2009-10-14 11:24:11

回答

6

根據我對CQRS的理解,您將創建一套DTO,滿足可能需要使用它們的用戶界面屏幕或應用程序的要求。

在項目中存在的地方基於需求,因爲這取決於您是否要通過Web服務公開這些DTO。 在這種情況下,我不會將它放在Web層中,而是放在應用層或專用的外牆層中。

然後,您將擁有隻讀存儲庫或數據訪問層,它直接填充DTO。我認爲事物的查詢方面應該優化讀取性能,在這種情況下,對數據庫視圖或表和SqlDataReaders的直接查詢/存儲過程將在這裏做最好的工作。但是肯定值得在接口後面抽象這個訪問,以便你可以在後面添加一個緩存的實現。

如果您使用的是ORM並希望從您的域實體映射到DTO,那麼您可以擁有一個通用的QueryRepository,該方法使用ISpecification或類似的構造來定義查詢,然後創建一個DtoAssembler對象來自您的Domain對象的Dtos。 然後,有一個實現爲您要執行的每個查詢都有第一個類對象。

這是一個相當人爲的例子,但我希望它給你一個想法。

 public interface ISpecification<T> 
     { 
      Expression<Func<T, bool>> Predicate { get; } 

     } 

     public class ActiveCustomersSpecification : ISpecification<Customer> 
     { 
      private Expression<Func<Customer, bool>> predicate; 
      public ActiveCustomersSpecification() 
      { 
       predicate = c => c.IsActive; 
      } 
      #region ISpecicfication<Customer> Members 

      public Expression<Func<Customer, bool>> Predicate 
      { 
       get { return predicate; } 
      } 

      #endregion 
     } 

     public interface IQueryRepository<T> 
     { 
      IQueryable<T> GetQuery(ISpecification<T> specification); 

      IEnumerable<T> FindAllBy(ISpecification<T> specification); 
     } 



public class CustomerDtoAssembler 
    { 
     public CustomerDto AssembleFrom(Customer customer) 
     { 
      var customerDto = new CustomerDto 
      { 
       Id = customer.Id 
      }; 

      return customerDto; 
     } 
    } 
+0

我發現這很有趣,你能澄清一件事嗎?查詢存儲庫和規範接口,它們都明確與ORM技術相耦合嗎?在這種情況下,我猜實體框架。它不應該是抽象的嗎? – 2016-10-15 20:02:15

3

我覺得willbt給你一個很好的starting point

我想補充一點,如果你確實選擇繼續使用ORM作爲查詢的數據訪問策略,那麼我們建議你考慮定製一個適合你期望訪問的數據的獲取策略(順便說一下,我在這裏專門討論NHibernate)。這意味着您可以決定是延遲加載還是急切加載與特定對象關聯的對象和集合。

Ritesh Rao的NCommon project提供了一個很好的(正在進行的)演示,演示如何爲不同目的定義不同的獲取策略。

Ritesh explains it really在他的博客。

來吧,看看源:

在測試 'Repository_For_Uses_​​Registered_Fetching_Strategies' 調用

NHRepository<Order>().For<NHRepositoryTests>() 

...導致fe針對要使用的NHRepositoryTests類進行註冊的策略,因此OrderItems和Products將被加載而不會搞亂NHibernate映射配置。

+1

這是一個有效的觀點。但是,它只適用於將實體返回到Facade層並映射到DTO的情況。我的建議是使用返回的IQueryable並將其直接投影到DTO中。這樣你可以避免任何FetchStrategies。 你甚至可以在NHibernate映射級別進行投影。 – willbt 2009-10-14 23:32:03

+0

當然!對了謝謝。我仍然接受NHibernate.Linq如何改變遊戲的觀點,但如果你看看Ritesh如何接受IQueryable,你會看到他認爲'能得到它'並且圍繞它建立好的東西(即需要一個規範表達式在他們的構造函數中)。現在更新到GitHub位置的 – rohancragg 2009-10-15 09:02:19

+0

鏈接 – rohancragg 2010-04-12 09:14:29