2010-11-23 57 views
1

我試圖建立一個查詢界面,用戶可以選擇任意一組過濾器最終從數據庫中獲取數據。我遇到的問題是,LINQ到SQL要麼不像我期望的那樣行事,要麼我做錯了什麼,因爲只有第一個有限的WHERE條件是通過SQL傳遞的。其他過濾的東西似乎正確發生,但從我所知道的情況來看,一旦數據已被提取,就會發生這種情況。LINQ/LINQ到SQL:有沒有一種方法可以使用組合的「where」過濾器來生成SQL?

這是我正在嘗試做的。

我有一個數據庫設置了會話表。我建立了我的LINQ到SQL的映射的東西,我取出過濾掉空註銷時間,以及任何額外的過濾器的「活動」會話用戶可以指定:

public static IEnumerable<Session> GetSessions(params Func<Session, bool>[] filters) 
{ 
    // I've created an auto-generate Linq-to-SQL context object with a Sessions table. 
    using (DataSourceDataContext ctx = new DataSourceDataContext()) 
    { 
     // Begin with all "active" sessions 
     IEnumerable<Session> sessions = ctx.Sessions.Where(x => x.LogoutTime == null); 
     foreach (var filter in filters) 
      sessions = sessions.Where(filter); 
     return sessions.ToArray(); 
    } 
} 

static void Main(string[] args) 
{ 
    Func<Session, bool> mySessions = (x => x.UserName == "steven"); 
    IEnumerable<Session> sessions = GetSessions(mySessions); 
} 

當我跑這個,我的所得組合是我期待(與用戶名=「史蒂芬」,即活動會話),但所請求的有效會話的完整列表從SQL(通過探查):

SELECT [t0].[ID], [t0].[UserName], [t0].[LoginTime], [t0].[LogoutTime], [t0].[Location] 
FROM [dbo].[Sessions] AS [t0] 
WHERE [t0].[LogoutTime] IS NULL 

我下的印象LINQ將繼續在幕後構建查詢,直到我遍歷我的集合,但我無法弄清楚爲什麼它沒有爲SQL部分做這件事。我錯過了什麼,或者我只是想讓LINQ-to-SQL做一些它不打算做的事情?

回答

3

您正在使用IEnumerable<T> - 這是相當-多限於處理數據本地,一旦你的單身.Where(...)LogoutTime物化;查詢組成要求IQueryable<T>。反過來,每個謂詞將要求Expression<Func<Session, bool>>

嘗試:

public static Session[] GetSessions(
    params Expression<Func<Session, bool>>[] filters) 
{ 
    // I've created an auto-generate Linq-to-SQL context object with 
    // a Sessions table. 
    using (var ctx = new DataSourceDataContext()) 
    { 
     // Begin with all "active" sessions 
     IQueryable<Session> sessions = ctx.Sessions 
      .Where(x => x.LogoutTime == null); 
     foreach (var filter in filters) 
      sessions = sessions.Where(filter); 
     return sessions.ToArray(); 
    } 
} 

您應該仍然能夠與lambda表達式調用這個,但如果你明確地處理Func<Session, bool>代表那些需要通過Expression<Func<Session, bool>>進行更新,以表達樹。

+0

工作非常感謝!你的解釋也有幫助,因爲我曾經想過IQueryable和IEnumerable之間的區別(我剛剛發現了表達式)。 – Steven 2010-11-23 22:17:41

2

您正在將第一個ctx.Sessions.Where()語句的結果分配給變量IEnumerable<Session>。這會導致後續篩選操作在IEnumerable上使用Where擴展方法,而不是IQueryable。 Queryable.Where方法是Linq2SQL linq提供程序可以將過濾謂詞(類型Expression>轉換爲實際SQL)的方法。Enumerable.Where接受Func委託,並將執行內存中的過濾

1

使用IQueryable替代IEnumerable

相關問題