2011-05-25 19 views
0

我現在有這樣對我倉庫裏的方法:如何構造部分動態的LINQ語句?

public int GetMessageCountBy_Username(string username, bool sent) 
    { 
     var query = _dataContext.Messages.AsQueryable(); 

     if (sent) 
      query = query.Where(x => x.Sender.ToLower() == username.ToLower()); 
     else 
      query = query.Where(x => x.Recipient.ToLower() == username.ToLower()); 

     return query.Count(); 
    } 

目前,它建立了基於該sent布爾兩個查詢之一。這是做到這一點的最佳方式,還是有一種方法可以在查詢本身內執行此操作嗎?我想檢查x.Sender是否等於username如果sent等於true。但是我想檢查x.Recipient是否等於username如果sent等於false。

然後我想要這個LINQ表達式轉換爲實體框架中的SQL,我相信它正在做。

我只是想避免重複儘可能多的代碼。

回答

2

你可以做這樣的事情:

public int GetMessageCountBy_Username(string username, bool sent) 
{ 
    Func<Message, string> userSelector = m => sent ? m.Sender : m.Recipient; 
    var query = 
    _dataContext.Messages.AsQueryable() 
    .Where(x => userSelector(x).ToLower() == username.ToLower()); 
    return query.Count(); 
} 

因此,正確的用戶(發件人或收件人)的選擇LINQ部分之前完成,從重複兩次拯救你。

+0

Bravo!這更有意義。謝謝。 – Chev 2011-05-25 13:45:27

+0

雖然我修改了一些功能。 lambda聲明必須先於inline IF語句。 – Chev 2011-05-25 17:03:02

+0

看起來我一直在接受答案時跳過槍。我應該先測試一下。這絕對有效,但不針對IQueryable 。表達式樹應該被翻譯成一個SQL表達式。這意味着這個LINQ語句不能調用另一個函數,所有相關的數據必須包含在表達式中才能使SQL翻譯起作用。一個.ToList()會使它工作,但會犧牲在數據源中執行查詢的能力。儘管謝謝你的回答! – Chev 2011-05-25 18:31:48

2

是的,我相信這是做到這一點的正確方法。因爲在不重複整個查詢部分的情況下創建複雜查詢很容易。

而你關於轉換爲SQL的想法也是正確的。但要小心,這是在數據或聚合被請求時完成的。在你的情況下,當你調用Count()時,SQL將被生成並執行。

+0

太棒了。是的,只要它在完整查詢構建完成後執行,那麼我很好。我不喜歡在我的存儲庫上返回'IQueryable '。我更喜歡給我的存儲庫更詳細的方法,比常規存儲庫做更多的工作。這種方式沒有延遲加載問題:) – Chev 2011-05-25 05:43:47