2015-11-04 61 views
4

讓我們使用博客上下文的經典示例。在我們的域名中,我們有以下情況:Users可以寫入PostsPosts必須至少在一個Category編目。可以使用Tags來描述PostsUsers可以對Posts發表評論。DDD/CQRS:結合UI要求的讀取模型

四個實體(PostCategoryTagComment)被實現爲由於我不同的聚集體沒有檢測到用於一個實體的數據應彼此干擾的任何規則。因此,對於每個聚合,我將有一個代表它的存儲庫。而且,每個聚合引用他人的id。

繼CQRS,從這個場景我已經扣除的命令,如WriteNewPostCommandPublishPostCommandDeletePostCommand等等各自的查詢以及從庫中獲取數據導致典型應用案例。 FindPostByIdQuery,FindTagByTagNameQuery,FindPostsByAuthorIdQuery等...

根據我們應用程序的哪個站點(後端或前端),我們將會有或多或少複雜的查詢。所以,如果我們在頭版,也許我們需要建立一些小部件來獲得最後的評論,最新的類別的帖子等等......涉及簡單的Query對象(很少搜索標準)和QueryHandler的查詢非常簡單(一個存儲庫作爲對處理程序類的依賴)

但在其他地方,此查詢可能更復雜。在管理面板中,我們需要在表格中顯示滿足複雜搜索條件的關係。可能是有趣的搜索帖子:作者姓名(無標識),類別名稱,標籤名稱,發佈日期......屬於不同聚合和不同存儲庫的標準。

此外,在我們的發佈表中,我們不想顯示帖子以及作者ID或類別ID。我們需要顯示所有信息(名稱用戶,頭像,類別名稱,類別圖標等)。

我的問題是:

  • 在基礎架構層,我們在設計庫,搜索方法(的findAll,findById,findByCriterias ...),應該返回相應的實體引用到的所有關聯的ID?我的意思是,如果有一個方法findPostById(uuid)findPostByCustomFilter(filter),應該返回一個post實例,並引用它具有的所有類別id,所有標籤id和它擁有的作者id?還是應該我的回購有某種方法來填充我想要的關聯給定的後期實例?

  • 如果我想搜索由John編寫並且分類爲「新聞」和「視頻」類別和標籤「科幻」和「冒險」的12/12/2014創建的帖子,並獲得完整每個彙總的詳細信息,應該如何創建我的QueryQueryHandler

a)創建與我的所有參數Query(AUTHORNAME,categoriesNames,TagsNames,如果想retrive UserCategoryTag協會全面詳細的),然後他QueryHandler ensamble不同的讀機型中唯一的一個。要麼...

二)創建不同Queries(FindCategoryByName,FindTagByName,FindUserByName),然後我的網絡控制器調用,以便日後 呼叫FindPostQuery但現在通過他的AUTHORID,類別ID,標籤識別來自其​​他查詢返回的?

b)解決方案看起來更乾淨,但看起來我更加昂貴。

回答

1

從CQRS你將有一個分離的查詢和命令堆棧。您的查詢堆棧應該代表項目中的差分模塊,名稱空間,dll或包。

a)您將創建一個QueryModel,並且此查詢模型將返回您需要的任何內容。如果您熟悉Entity Framework或NHibernate,您將創建一個Façade來容納此查詢,DbContext或Session。

b)你可以創建這個分離的查詢,但再說一遍,如果你熟悉任何ORM,你應該返回代表模型的集合,將每個集合返回爲IQueryable並使用LET(Linq Expression Trees)使你的查詢堆棧更加動態。

使用實體框架和C#的爲例:

public class QueryModelDatabase : DbContext, IQueryModelDatabase 
{ 
    public QueryModelDatabase() : base("dbname") 
    { 
     _products = base.Set<Product>(); 
     _orders = base.Set<Order>(); 
    } 

    private readonly DbSet<Order> _orders = null; 
    private readonly DbSet<Product> _products = null; 

    public IQueryable<Order> Orders 
    { 
     get { return this._orders.Include("Items").Include("Items.Product"); } 
    } 

    public IQueryable<Product> Products 
    { 
     get { return _products; } 
    } 
} 

那麼你應該做的查詢你需要的方式和返回任何東西:

using (var db = new QueryModelDatabase()) 
{ 
    var queryable = from o in db.Orders.Include(p => p.Items).Include("Details.Product") 
        where o.OrderId == orderId 
        select new OrderFoundViewModel 
        { 
         Id = o.OrderId, 
         State = o.State.ToString(), 
         Total = o.Total, 
         OrderDate = o.Date, 
         Details = o.Items 
        }; 
    try 
    { 
     var o = queryable.First(); 
     return o; 
    } 
    catch (InvalidOperationException) 
    { 
     return new OrderFoundViewModel(); 
    } 
} 
3
  • 在查詢方面,有沒有實體。您可以以任何最適合您的要求的方式自由填充您閱讀的模型。無論您需要在屏幕上顯示哪些數據(部分),都可以將其放入讀取模型中。這不是返回這些讀取模型而是專用查詢端數據訪問對象的命令端存儲庫。

  • 您提到了「複雜的搜索條件」 - 我建議您使用相應的SearchCriteria對象進行建模。這個對象應該是技術上不可知的,但是它會被傳遞給你的查詢端數據訪問對象,這個對象將知道如何組合標準來爲它所針對的特定數據存儲構建一個較低級別的查詢。