假设我有一个IQueryable<T>表达式,我想封装它的定义,将其存储并重用,或者稍后将其嵌入更大的查询中。例如:

IQueryable<Foo> myQuery =
    from foo in blah.Foos
    where foo.Bar == bar
    select foo;

现在,我相信我可以只保留该myQuery对象,并按照我的描述使用它。但是有些事情我不确定:
  • 如何最好地对其进行参数化? 最初,我在方法中定义了此方法,然后返回IQueryable<T>作为方法的结果。这样,我可以将blahbar定义为方法参数,并且我猜每次它只是创建一个新的IQueryable<T>。这是封装IQueryable<T>逻辑的最佳方法吗?还有其他方法吗?
  • 如果我的查询解析为标量而不是IQueryable怎么办? 例如,如果我希望此查询与显示的完全一样,但附加.Any()只是让我知道是否有任何匹配的结果,该怎么办?如果我添加(...).Any(),那么结果就是bool并立即执行,对吗?有没有一种方法可以立即使用这些Queryable运算符(AnySindleOrDefault等)? LINQ-to-SQL如何处理此问题?

  • 编辑:第2部分实际上更多地是关于尝试了解IQueryable<T>.Where(Expression<Func<T, bool>>)IQueryable<T>.Any(Expression<Func<T, bool>>)之间的限制差异是什么。在创建较大的查询(延迟执行时间)时,后者似乎没有那么灵活。可以附加Where(),然后再附加其他结构,然后最终执行。由于Any()返回一个标量值,因此听起来好像它将立即执行,然后才能构建其余的查询。

    最佳答案

  • 使用DataContext时,在传递IQueryable时必须非常小心,因为一旦处置了上下文,您将无法在该IQueryable上执行。如果您不使用上下文,那么可能会没事,但是请注意这一点。
  • .Any()和.FirstOrDefault()是,而不是。当您调用它们时,它们将导致发生执行。但是,这可能无法实现您认为的目的。例如,在LINQ to SQL中,如果对IQueryable执行.Any(),则它基本上充当IF EXISTS(SQL HERE)。

  • 如果要执行以下操作,可以像这样将IQueryable链接起来:
    var firstQuery = from f in context.Foos
                        where f.Bar == bar
                        select f;
    
    var secondQuery = from f in firstQuery
                        where f.Bar == anotherBar
                        orderby f.SomeDate
                        select f;
    
    if (secondQuery.Any())  //immediately executes IF EXISTS( second query in SQL )
    {
        //causes execution on second query
        //and allows you to enumerate through the results
        foreach (var foo in secondQuery)
        {
            //do something
        }
    
        //or
    
        //immediately executes second query in SQL with a TOP 1
        //or something like that
        var foo = secondQuery.FirstOrDefault();
    }
    

    关于c# - 如何维护LINQ延迟执行?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1308129/

    10-17 00:57