4

說我正在創建一個存儲數字電子書的存儲庫,如下面的界面所示。這個存儲庫將存儲書的實際文本,以及標識書的元數據(標題,作者,出版商,ISBN等)。DDD存儲庫可以使用摘要對象來處理「真實」對象嗎

public interface IBookRepository 
{ 
    void AddBook(Book newBook); 
    void DeleteBook(int bookId); 
    void UpdateBook(Book updatedBook); 
    Book GetBook(int bookID) 
} 

public class Book 
{ 
    public int BookId {get; set;} 
    public string Title {get; set;} 
    public string Author {get; set;} 
    public IList<Page> Contents {get; set} 
} 

public class Page 
{ 
    public int PageNumber {get; set;} 
    public string PageContent {get; set;} 
} 

在大多數情況下,我不希望檢索該書整個文本,因爲這將是相當昂貴的。在大多數情況下,我關心的是元數據,例如我可能只是想創建一個書目清單。那麼在DDD方面也可以允許IBookRepository擁有返回BookSummary對象的方法嗎?書摘要對象將包括元數據,但不包括書的實際內容。

怎麼樣有一個UpdateBook(BookSummary book)方法?假設我想更新Book.Rating屬性,但不需要/希望從存儲庫讀取本書的全部內容來執行此操作。

public interface IBookRepository 
{ 
    //Full Book Methods 
    void AddBook(Book newBook); 
    void DeleteBook(int bookId); 
    void UpdateBook(Book updatedBook); 
    Book GetBook(int bookID) 

    //BookSummary Methods 
    BookSummary GetBookSummary(int bookID) 
    IEnumerable<BookSummary> GetBooksByAuthor(string authorName); 
    IEnumerable<BookSummary> GetBooksByGenre(int genreId); 
    void UpdateBook(BookSummary bookSummary); 
} 


public class BookSummary 
{ 
    public int BookId {get; set;} 
    public string Title {get; set;} 
    public string Author {get; set;} 
    public int PageCount {get; set;} 
} 

注:我知道使用帶有延遲加載的ORM也將是一個解決方案,但我想用的是延遲加載將用於

回答

2

的假設來設計我的資料庫如果你的域中有一個用例支持它,那麼爲什麼不只是用它自己的Repository創建額外的實體BookSummary來完成這項工作? BookSummary的持續位置並不重要 - 它與域無關。

使用無處不在的語言從域中派生實體很重要,而不是查看數據庫結構。

public interface IBookRepository 
{ 
    //Full Book Methods 
    void Add(Book Book); 
    void Delete(Book Book); 
    Book findById(int bookID) 
} 

public interface IBookSummaryRepository 
{ 
    //Full Book Summary Methods 
    void Add(BookSummary BookSum); 
    void Delete(BookSummary BookSum); 
    Book findById(int bookSummaryID) 
} 

如果你的版本庫的方法更新()或存儲(),它比存儲庫更容易通過DAO DDD:http://codebetter.com/iancooper/2011/04/12/repository-saveupdate-is-a-smell/

+0

是但是如果將圖書添加到IBookRespository中,我的域名確實期望找到BookSummary。如果它們是獨立的存儲庫,那麼無法確保將Book添加到另一個會導致BookSummary出現在另一箇中。當然你可以設置兩個存儲庫指向同一個數據庫表,但這將是一個特定的實現。對我來說,有一個存儲庫意味着來自存儲庫的所有數據來自同一個數據存儲。看到我最新的與此相關的SO問題:http://bit.ly/jjUhbi – 2011-06-10 05:42:40

+0

您可以從另一個庫調用一個存儲庫。 – 2011-06-10 08:09:50

+0

我認爲存儲庫不應該調用其他存儲庫:http://stackoverflow.com/questions/1364461/should-a-repository-call-another-repository-or-should-a-repository-call-a-servic, – 2011-06-10 20:53:39

2

在DDD庫應與聚合根才能正常工作。就你而言,我認爲BookSummary只是Book聚合中的一個實體(當然,這裏需要更精確的分析),所以應該通過BookRepository獲取Book,然後使用延遲加載從聚合根遍歷到BookSummary。否則,您並未在此處應用域名驅動設計

+0

我已經爲BookSummary添加了代碼。我不認爲BookSummary是Book集合中的一個實體。 BookSummary與相應的Book具有相同的ID。它只是以不同的形式呈現相同的東西。這只是一本書的簡化/代理版本。我明白,使用帶有延遲加載的ORM將刪除對BookSummary類型的需求。然而,假設將使用延遲加載來設計存儲庫似乎沒有比設計存儲庫時更爲正確,因爲假設將使用SQL Server。接口應該獨立於實現。 – 2011-06-10 08:29:29

+0

我建議你沒有BookSummary。這裏有幾個選項可以做到這一點:1.只加載需要的數據(使用惰性屬性或投影)2.引入分離的讀取優化存儲(在此應用CQRS原理)3.將Book分解爲Book和BookText(這裏沒有重複數據與您在當前模型中的數據相同)。無論如何,如果你沒有引入讀取存儲,你將不得不加載ENTIRE聚合(使用延遲加載或不加載)。如果你不這樣做,你會採用數據驅動的方法 – xelibrion 2011-06-10 11:05:31

0

這是一個老問題,但沒有可接受的答案,因此我將回答爲Google在此處登錄的用戶所帶來的好處。由於我們有許多摘要屏幕顯示部分信息和/或從多個實體編譯的信息,所以我一直在討論這個問題。我所做的是使用@xelibrion在其答案的評論中提出的單獨讀取模型。我沒有使用完整的CQRS,只是使用查詢方法進行簡單的讀取模型。所以你BookRepository仍然像這樣:

public interface IBookRepository 
{ 
    void AddBook(Book newBook); 
    void DeleteBook(int bookId); 
    void UpdateBook(Book updatedBook); 
    Book GetBook(int bookID) 
} 

而且你BookSummary閱讀模式和它的方法是這樣的:

public class BookSummary 
{ 
    public int BookId {get; set;} 
    public string Title {get; set;} 
    public string Author {get; set;} 
    public int PageCount {get; set;} 
} 

public interface IBookSummaryQueries 
{ 
    BookSummary GetBookSummary(int bookID) 
    IEnumerable<BookSummary> GetBooksByAuthor(string authorName); 
    IEnumerable<BookSummary> GetBooksByGenre(int genreId); 
} 

注意,有沒有方法來更新此預訂,只需查詢