如何LINQ推迟执行在using语句时, [英] How does LINQ defer execution when in a using statement

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

问题描述

想象一下,我有以下几点:

Imagine I have the following:

private IEnumerable MyFunc(parameter a)
{
   using(MyDataContext dc = new MyDataContext)
   {
      return dc.tablename.Select(row => row.parameter == a);
   }
}

private void UsingFunc()
{
   var result = MyFunc(new a());

   foreach(var row in result)
   {
      //Do something
   }
}

根据文档的LINQ执行将推迟,直到我实际列举的结果,发生在该行处的foreach。然而,使用的语句应该强制对象被可靠地调用MyFunct()结束时收集的。

According to the documentation the linq execution will defer till I actual enumerate the result, which occurs in the line at the foreach. However the using statement should force the object to be collected reliably at the end of the call to MyFunct().

究竟会发生,何时会处置的运行和/或结果跑?

What actually happens, when will the disposer run and/or the result run?

我唯一能想到的就是延迟执行计算在编译时,所以实际调用由编译器移动到的foreach的第一线,导致用正确执行,但不能运行,直到在foreach线? 有没有一个大师在那里谁可以帮助?

Only thing I can think of is the deferred execution is computed at compile time, so the actual call is moved by the compiler to the first line of the foreach, causing the using to perform correctly, but not run until the foreach line? Is there a guru out there who can help?

编辑:<打击>注:此code不工作,我只是不明白怎么

我做了一些阅读,我意识到我的code,我已经叫这当然列举的结果了ToList()扩展方法。该勾选答案的行为是完全正确的实际问题的回答。

I did some reading and I realised in my code that I had called the ToList() extension method which of course enumerates the result. The ticked answer's behaviour is perfectly correct for the actual question answered.

抱歉任何混乱。

推荐答案

我预计,根本没有工作;在选择被推迟,所以没有数据被消耗在这一点上。但是,既然你已经设置在数据上下文(临行前 MYFUNC ),这将永远无法获得的数据。更好的选择是通过数据上下文的的方法,从而使消费者可以选择的寿命。另外,我建议返回的IQueryable&LT; T&GT; 使消费者能够撰写的结果(即加入排序依据 / 跳过 / / 其中,等,并将其影响最终的查询):

I would expect that to simply not work; the Select is deferred, so no data has been consumed at this point. However, since you have disposed the data-context (before leaving MyFunc), it will never be able to get data. A better option is to pass the data-context into the method, so that the consumer can choose the lifetime. Also, I would recommend returning IQueryable<T> so that the consumer can "compose" the result (i.e. add OrderBy / Skip / Take / Where etc, and have it impact the final query):

// this could also be an instance method on the data-context
internal static IQueryable<SomeType> MyFunc(
    this MyDataContext dc, parameter a)
{
   return dc.tablename.Where(row => row.parameter == a);
}

private void UsingFunc()
{
    using(MyDataContext dc = new MyDataContext()) {
       var result = dc.MyFunc(new a());

       foreach(var row in result)
       {
           //Do something
       }
    }
}



更新:如果你(的意见)不希望推迟执行(即不希望处理数据上下文调用者),那么你需要评估结果。您可以通过调用做到这一点 .ToList() .ToArray()的结果缓冲区中的值。

Update: if you (comments) don't want to defer execution (i.e. you don't want the caller dealing with the data-context), then you need to evaluate the results. You can do this by calling .ToList() or .ToArray() on the result to buffer the values.

private IEnumerable<SomeType> MyFunc(parameter a)
{
   using(MyDataContext dc = new MyDataContext)
   {
      // or ToList() etc
      return dc.tablename.Where(row => row.parameter == a).ToArray();
   }
}

如果你想保持它在这种情况下延期,那么你就需要使用迭代器块:

If you want to keep it deferred in this case, then you need to use an "iterator block":

private IEnumerable<SomeType> MyFunc(parameter a)
{
   using(MyDataContext dc = new MyDataContext)
   {
      foreach(SomeType row in dc
          .tablename.Where(row => row.parameter == a))
      {
        yield return row;
      }
   }
}

这是现在推迟周围没有传递数据上下文。

This is now deferred without passing the data-context around.

这篇关于如何LINQ推迟执行在using语句时,的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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