如何保持LINQ延迟执行? [英] How to maintain LINQ deferred execution?

查看:111
本文介绍了如何保持LINQ延迟执行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个的IQueryable< T> 表达,我想封装的定义,存储并重复使用或以后在一个大的查询嵌入。例如:

 的IQueryable<富>更改为MyQuery = $ B从foo在blah.Foos 
$ b,其中foo.Bar ==酒吧
选择foo的;

现在我相信,我可以只保留了更改为MyQuery对象周围和我一样描述使用它。但有些事情我不知道?




  1. 如何最好地将其参数化起初我'已经在方法定义了这个,然后返回的IQueryable< T> 作为方法的结果。这样我可以定义等等作为方法的参数,我想这只是创建了一个新的 IQueryable的< T> 各一次。这是封装的逻辑的最佳途径的IQueryable< T> ?是否有其他方法吗?


  2. 如果我的查询解析为一个标量,而不是的IQueryable 举例来说,如果我想这是什么查询与所示但附加。任何()来只是让我知道,如果有匹配的任何结果?如果我添加(...)。任何(),那么结果是布尔并立即执行,对不对?有没有使用这些可查询运算符(任何 SindleOrDefault 等),但不立即执行?如何LINQ到SQL处理这个




编辑:第2部分是真的更多关于试图了解什么是之间的的IQueryable<限制差异; T>。凡(表达式来; Func键< T,BOOL>>)与 IQueryable的< T>。任何(表达式来; Func键< T,BOOL>>)。它好像创造更大的查询,其中在执行要被延迟时,后者是不够灵活。在其中()可以追加,然后其他的结构可以在以后追加,最后执行。因为任何()返回一个标值,这听起来像它会查询可建的其余部分之前立即执行。

解决方案

  1. 您必须非常小心周围IQueryables路过当你使用一个DataContext,因为一旦场景中获得的处置,你赢了'T能够在该IQueryable的执行了。如果你不使用上下文,那么你可能是好的,但要注意这一点。


  2. 。任何()和.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:

  1. 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 define blah and bar as method arguments and I guess it just creates a new IQueryable<T> each time. Is this the best way to encapsulate the logic of an IQueryable<T>? Are there other ways?

  2. 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 is bool and immediately executed, right? Is there a way to utilize these Queryable 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.

解决方案

  1. 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.

  2. .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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆