2012-10-09 34 views
0

鑑於兩類類似於NHibernate LinqProvider/IQueryable:在Where子句中支持FirstOrDefault()嗎?

public class Blog 
{ 
    public virtual int BlogId { get; set; } 
    public virtual IList<Comment> Comments { get; set; } 
} 

public class Comment 
{ 
    public virtual int CommentId { get; set; } 
    public virtual Blog Blog { get; set; } 
    public string Title { get; set; } 
} 

我用下面的語句有一個困難時期:

session.Query<Blog>.Where(b => b.Comments.FirstOrDefault().Title.Contains("my title"))); 

拋出的錯誤是:

Antlr.Runtime.NoViableAltException

使用.Any()工程:

session.Query<Blog>.Where(b => b.Comments.Any(c => c.Title.Contains("my title"))); 

但是,這不是我想要的。實際上,這不是關於博客和評論,而是關於版本化實體。在他們的父實體的映射中,我通過他們的版本號來訂購它們的集合。我需要能夠訪問第一個條目才能獲得最新版本。

+0

它不支持,因爲像'FirstOrDefault方法( )','ToList()',它們將IQueryable完成爲具體類型(原語類型,唯一實體和列表)。如果你調用這樣的東西,你將會得到一個異常,因爲你仍然在執行的上下文中,這使你無法運行子查詢。在這種情況下,您必須使用'.Any'方法,因爲它會在SQL語句中生成一個子選擇。 –

+0

要解決您的問題,您可以在存儲庫中添加一個方法,以獲得帶有idBlog的第一條評論。 –

+0

@Felipe Orani:這是一個複雜查詢的一部分,並且爲每個Blog啓動一個選擇將不會很好。黑客將添加FirstCommentId屬性到實體博客並通過公式映射該屬性(「Select Top 1 CommentId from ...」),然後執行.Any(c => c.CommentId == b.FirstCommentId && c.Title.Contains(「我的標題」) – kitsune

回答

0

爲什麼不在db中預先篩選並使用linq來最終過濾對象呢?

var results = session.Query<Blog>() 
    .Where(b => b.Comments.Any(c => c.Title.Contains("my title"))) 
    .AsEnumerable() 
    .Where(b => b.Comments[0].Title.Contains("my title"))) 
    .ToList(); 

,或者如果Listposition在評論(這是不漂亮)

Map(x => x.Position, "listindexcolumn").ReadOnly(); 

var results = session.Query<Blog>() 
    .Where(b => b.Comments.Any(c => c.Position == 0 && c.Title.Contains("my title"))) 
    .ToList(); 

或使用查詢唯一的財產

Map(x => this.Position, "listindexcolumn").ReadOnly().Access.None(); 

var results = session.CreateCriteria<Blog>() 
    .CreateCriteria("Comments") 
     .Add(Restriction.Eq("Position", 0) && Restriction.Like("Title", "my title")) 
    .ToList<Blog>();