如何保持LINQ延迟执行? [英] How to maintain LINQ deferred execution?
问题描述
假设我有一个的IQueryable< T>
表达,我想封装的定义,存储并重复使用或以后在一个大的查询嵌入。例如:
的IQueryable<富>更改为MyQuery = $ B从foo在blah.Foos
$ b,其中foo.Bar ==酒吧
选择foo的;
现在我相信,我可以只保留了更改为MyQuery对象周围和我一样描述使用它。但有些事情我不知道?
-
如何最好地将其参数化起初我'已经在方法定义了这个,然后返回
的IQueryable< T>
作为方法的结果。这样我可以定义等等
和栏
作为方法的参数,我想这只是创建了一个新的IQueryable的< T>
各一次。这是封装的逻辑的最佳途径的IQueryable< T>
?是否有其他方法吗? -
如果我的查询解析为一个标量,而不是
的IQueryable
?举例来说,如果我想这是什么查询与所示但附加。任何()
来只是让我知道,如果有匹配的任何结果?如果我添加(...)。任何()
,那么结果是布尔
并立即执行,对不对?有没有使用这些可查询
运算符(任何
,SindleOrDefault $ C $方式C>等),但不立即执行?如何LINQ到SQL处理这个
编辑:第2部分是真的更多关于试图了解什么是之间的的IQueryable<限制差异; T>。凡(表达式来; Func键< T,BOOL>>)与
。它好像创造更大的查询,其中在执行要被延迟时,后者是不够灵活。在
IQueryable的< T>。任何(表达式来; Func键< T,BOOL>>)其中()
可以追加,然后其他的结构可以在以后追加,最后执行。因为任何()
返回一个标值,这听起来像它会查询可建的其余部分之前立即执行。
-
您必须非常小心周围IQueryables路过当你使用一个DataContext,因为一旦场景中获得的处置,你赢了'T能够在该IQueryable的执行了。如果你不使用上下文,那么你可能是好的,但要注意这一点。
-
。任何()和.FirstOrDefault()是<强>不可以推迟。当你打电话给他们,他们的会发生原因执行。但是,这可能不是做什么,你认为它。例如,LINQ to SQL的,如果你在一个IQueryable它作为一个IF EXISTS(SQL HERE)基本相符。
执行。任何()
您可以链的IQueryable沿着这样的,如果你想的:
VAR firstQuery =从步骤f上下文.Foos
,其中f.Bar ==酒吧
,选择F;
VAR secondQuery =从f由于firstQuery
,其中f.Bar == anotherBar
排序依据f.SomeDate
选择F;
如果(secondQuery.Any())//立即执行IF EXISTS(SQL中的第二个查询)
{
//导致在第二次查询
执行//并允许您通过结果
枚举的foreach(在secondQuery VAR富)
{
//做些什么
}
//或
//立即执行SQL中使用TOP 1
//或类似的东西
变种foo的第二个查询= secondQuery.FirstOrDefault();
}
Suppose I have an IQueryable<T>
expression that I'd like to encapsulate the definition of, store it and reuse it or embed it in a larger query later. For example:
IQueryable<Foo> myQuery =
from foo in blah.Foos
where foo.Bar == bar
select foo;
Now I believe that I can just keep that myQuery object around and use it like I described. But some things I'm not sure about:
How best to parameterize it? Initially I've defined this in a method and then returned the
IQueryable<T>
as the result of the method. This way I can defineblah
andbar
as method arguments and I guess it just creates a newIQueryable<T>
each time. Is this the best way to encapsulate the logic of anIQueryable<T>
? Are there other ways?What if my query resolves to a scalar rather than
IQueryable
? For instance, what if I want this query to be exactly as shown but append.Any()
to just let me know if there were any results that matched? If I add the(...).Any()
then the result isbool
and immediately executed, right? Is there a way to utilize theseQueryable
operators (Any
,SindleOrDefault
, etc.) without immediately executing? How does LINQ-to-SQL handle this?
Edit: Part 2 is really more about trying to understand what are the limitation differences between IQueryable<T>.Where(Expression<Func<T, bool>>)
vs. IQueryable<T>.Any(Expression<Func<T, bool>>)
. It seems as though the latter isn't as flexible when creating larger queries where the execution is to be delayed. The Where()
can be appended and then other constructs can be later appended and then finally executed. Since the Any()
returns a scalar value it sounds like it will immediately execute before the rest of the query can be built.
You have to be really careful about passing around IQueryables when you're using a DataContext, because once the context get's disposed you won't be able to execute on that IQueryable anymore. If you're not using a context then you might be ok, but be aware of that.
.Any() and .FirstOrDefault() are not deferred. When you call them they will cause execution to occur. However, this may not do what you think it does. For instance, in LINQ to SQL if you perform an .Any() on an IQueryable it acts as a IF EXISTS( SQL HERE ) basically.
You can chain IQueryable's along like this if you want to:
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();
}
这篇关于如何保持LINQ延迟执行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!