【问题标题】:When IQueryable is created from a linq query why is it not a "new" variable?当从 linq 查询创建 IQueryable 时,为什么它不是“新”变量?
【发布时间】:2010-12-07 07:39:37
【问题描述】:

我正在使用实体框架,并且有一个循环来查看一组人员,并使用 foreach 循环为每个人的地址创建一个查询。在创建每个地址查询时,它被添加到树视图的节点中,以后可以使用它(填充子节点):

 IQueryable<Person> pQuery = (IQueryable<Person>)myContext.People; //get a list of people

 //go through and get the set of addresses for each person
 foreach (var p in pQuery)
 {
      var addressQuery = from a in myContext.Addresses
                                   from al in a.Address_Links
                                   where al.P_ID == p.P_ID
                                   orderby a.A_POST_CODE
                                   select a;


     //add the query to a TreeView node (use the tag to store it)
     TreeNode newNode = new TreeNode();
     newNode.Tag = addressQuery;
 }

现在,我在运行应用程序时发现的问题是所有查询都是创建的最后一个查询,即循环的最后一次迭代。就像 addressQuery 是在循环的第一次迭代中创建的,然后在每个后续查询中被覆盖。这样做的结果是,就像树节点中的所有地址查询都是对最后一次查询的引用(?)

进一步调查,我可以通过使用静态类生成地址查询并将其传递给每个 TreeNode 来解决问题,如下所示:

 public static class Queries
    {
        public static IQueryable<Address> AddressesForPerson(GenesisEntities myContext, int key)
        {
            var query = from a in myContext.Addresses
                        from al in a.Address_Links
                        where al.P_ID == key
                        orderby a.A_POST_CODE
                        select a;
            return query;
        }

}

我的问题是我对这种行为感到困惑。为什么拥有一个静态查询类对我有帮助?谁能给我解释一下这是怎么回事?

Confused.Com!

【问题讨论】:

    标签: linq entity-framework byref


    【解决方案1】:

    原因是p 变量(foreach 循环变量)被捕获并且查询被延迟评估。结果,当查询实际运行时,它使用了当时p变量的当前值,也就是最后一个值。阅读my answer to "What is the exact definition of a closure?"了解更多信息。

    要解决这个问题,只需尝试引入一个临时变量:

     // `loopVariable` is scoped inside loop body AND the loop declaration.
     foreach (var loopVariable in pQuery) 
     {
          var p = loopVariable; // This variable is scoped **inside** loop body.
          var addressQuery = from a in myContext.Addresses
                                       from al in a.Address_Links
                                       where al.P_ID == p.P_ID
                                       orderby a.A_POST_CODE
                                       select a;
    
    
         //add the query to a TreeView node (use the tag to store it)
         myTreeView.Tag = addressQuery
     }
    

    【讨论】:

    • 哇!这是一个地狱般的陷阱!谢谢梅尔达德
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-02
    • 1970-01-01
    • 1970-01-01
    • 2022-06-27
    • 1970-01-01
    • 2019-06-29
    • 2015-10-03
    相关资源
    最近更新 更多