2010-11-23 31 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

相关问题