在foreach语句中更改Linq对象?

时间:2012-12-13 11:54:51

标签: c# linq foreach

考虑一下这里我有一个Linq表类,我想在foreach语句中查询这个对象:

      IQueryable< tab_policy> Result=from c in db.tab_policy select c;

      foreach(int i=0;i<3;i++)
      {
      Result = from c in Result
                 join d in db.tab_reg_type_one_to_many.Where(a => a.reg_id==i)
                on c.poli_id equals d.poli_id
                 select c;
       }

如何根据前一次迭代的值更改每次迭代中的Result变量? 我在这个例子中得到的值只等于最后一次迭代而不是所有迭代在一起,而在这种情况下,在每次迭代中,结果在foreach内部发生变化。 虽然当我使用这个迭代而没有foreach时,它可以正常工作。

       Result = from c in Result
                 join d in db.tab_reg_type_one_to_many.Where(a => a.reg_id==0)
                on c.poli_id equals d.poli_id
                 select c;
      Result = from c in Result
                 join d in db.tab_reg_type_one_to_many.Where(a => a.reg_id==1)
                on c.poli_id equals d.poli_id
                 select c;
      Result = from c in Result
                 join d in db.tab_reg_type_one_to_many.Where(a => a.reg_id==2)
                on c.poli_id equals d.poli_id
                 select c;

2 个答案:

答案 0 :(得分:2)

问题的技术原因是循环变量i在每个Where委托中捕获,但在每次迭代中都被修改。这意味着:当执行查询时(循环之后),仅使用i的最后一个值。这可以通过类似var j = ij中的Where来解决。

但真正的解决方案更简单:

var ids = Enumerable.Range(0,i).ToList();
Result = from c in Result
         join d in db.tab_reg_type_one_to_many.Where(a => ids.Contains(a.reg_id))
             on c.poli_id equals d.poli_id
         select c;

修改 正确评论时,此解决方案不同于3个连接。差异是微妙和难以捉摸的。通过三个(或n)联接,您可以抓取c.poli_id等于d.poli_id三次的记录,而不是1-3次。因此,毕竟解决方案是防止修改后的闭包:

for(int i = 0; i < 3; i++)
{
    var j = i;
    Result = from c in Result
             join d in db.tab_reg_type_one_to_many.Where(a => a.reg_id == j)
                on c.poli_id equals d.poli_id
             select c;
}

答案 1 :(得分:0)

@GertArnold感谢您的回答。这个解决方案也不正确。相反,我用List替换了IQueryable并解决了问题,因为IQueryable是在需要时计算的,所以它是通过延迟计算的,但List不是那样的,所以最终的解决方案是:

  List<tab_policy> Result = (from c in db.tab_policy select c).ToList();
  foreach(int i=0;i<3;i++)
  {
  Result = from c in Result
             join d in db.tab_reg_type_one_to_many.Where(a => a.reg_id==i)
            on c.poli_id equals d.poli_id
             select c;
   }