2010-05-05 76 views
14

我有一個具有屬性集合的根對象。作爲根屬性的NHibernate IQueryable集合

例如:

I have a Shelf object that has Books. 

// Now 
public class Shelf 
{ 
    public ICollection<Book> Books {get; set;} 
} 

// Want 
public class Shelf 
{ 
    public IQueryable<Book> Books {get;set;} 
} 

我想做到的是返回一個集合,是IQueryable的,這樣我可以從父直接運行尋呼和過濾掉的集合。

var shelf = shelfRepository.Get(1); 

var filtered = from book in shelf.Books 
       where book.Name == "The Great Gatsby" 
       select book; 

我想有由NHibernate的具體執行的查詢,並沒有得到所有加載整個集合,然後在內存中分析它(這是當我使用的ICollection什麼目前發生)。

這背後的原因是,我的收藏可能是巨大的,成千上萬的記錄,並且讓所有的查詢可以來砸我的數據庫。

我想,這樣當NHibernate的看在我的班級一個IQueryable它知道怎樣做才能做到這一點含蓄。

我已經看過了NHibernate的LINQ提供程序,目前我正在服用大集合和他們分裂成自己的資源庫,這樣我可以作出的篩選和分頁顯式調用的決定。

的LINQ to SQL提供類似於我在談論的東西。

回答

12

我一直在想出一個類似問題的解決方案。

您可以使用ISession.FilterCollection從集體中過濾集合。這會創建一個額外的IQuery,您可以在其中統計頁數,添加條件等。

因此,舉例來說(我在FilterCollection查詢可能有點過,但你應該明白我的意思):

ISession session = GetSession(); 
var shelf = session.Get<Shelf>(id); 
var books = session.FilterCollection(shelf.Books, "where Name = :title").SetString("title", "The Great Gatsby").List<Book>(); 

有有一個問題,但是:

  1. 的執行代碼 的消費者需要訪問 ISession.CreateFilter,或者您需要 以在您的 存儲庫中創建一個方法,該方法接受屬性 查詢以及查詢參數 (以及任何尋呼或其他 信息)。並不是這個星球上最性感的東西 。
  2. 這不是你想要的LINQ。

不幸的是,我不認爲有什麼辦法可以用NHibernate來獲得你想要的東西。你可以假的吧,如果你想嘗試,但他們似乎落空對我說:

添加的方法或屬性,在幕後返回的LINQ to NHibernate的IQueryable的此架

public IQueryable<Book> FindBooks() { 
    return Resolver.Get<ISession>().Linq<Book>().Where(b => b.Shelf == this); 
} 

如果有人可能會消耗是這樣的:

var shelf = ShelfRepo.Get(id); 
var books = (from book shelf.FindBooks() 
      where book.Title == "The Great Gatsby" 
      select book); 

呸!你正在通過你的領域模型消除你的持久性需求!也許你可以把它由具有存儲庫少一些糟糕發出的IQueryable,它在運行時實際上是LINQ NHibernate的:

public IQueryable<Book> FindBooks() { 
    return Resolver.Get<IRepository<Book>>().CreateQuery().Where(b => b.Shelf == this); 
} 

還是蠻等等。

創建您自己的自定義集合類型(可能是IQueryable實現),它包裝實際書籍的專用字段,並將NHibernate映射到該字段。但是,使用ISession.CreateFilter可能會遇到困難。您必須考慮「發現」當前會話,將LINQ表達式轉換爲您可以在CreateFilter中使用的東西等。另外,您的業務邏輯仍然依賴於NHibernate。

在這一點上沒有什麼可以滿足的。直到NHibernate可以爲您的集合執行LINQ之前,看起來您最好像查詢過的那樣正常查詢您的Book存儲庫,即使它看起來不夠性感或最佳。

+0

謝謝你的解釋如此詳盡。我想過你說過的話,我同意你提出的所有觀點。不知道NHibernate 3是否會支持這個開箱即用的功能。 – 2010-05-15 14:19:42

1

也許你應該試一試Nhibernate Linq。它允許您使用IQueryable的和不喜歡的事情:

Session.Linq<Book>().Where(b => b.Name == "The Great Gatsby"); 
+0

「我看過NHibernates Linq提供程序,目前我正在決定採用大型集合並將它們拆分到自己的存儲庫中,以便我可以明確調用篩選和分頁。」 – 2010-05-06 01:16:00

+2

@哈立德 - 我不知道爲什麼這不會幫助你。這正是你要求的 – Dann 2010-05-06 08:14:37

+0

我的問題是「我如何獲得NHibernate映射到IQueryable屬性?」我已經知道NHibernate Linq。這是我從未問過的問題的答案,這就是爲什麼我投了票。 – 2010-05-07 13:31:10

3

我傾向於認爲是這樣的:

總根源是一致的邊界,因此,如果貨架需要實施某種書本上的一致性政策它包含,那麼它應該是一個聚合根。 而在這種情況下,它應該擁有一套/一套書。

如果你不需要從架子上的書執行任何方式的一致性,那麼我會考慮刪除組/集合屬性,然後將這些查詢到存儲庫來代替。

而且,由於分頁和篩選最有可能沒有什麼與你的域邏輯,它是最有可能的表現。 然後我會考慮爲它製作一些特別的視圖,而不是向我的存儲庫添加演示設備。

例如

var result = Queries.FindBooksByShelf(shelfId,pageSize); 

這種查詢可以返回的突起和/或作爲普通的SQL優化等 他們是有一定看法最有可能的特定或在您的GUI報告。 這樣你的域名將只專注於域名概念。

相關問題