2009-10-16 47 views
2

我正在使用實體框架,並有一個循環查看一組人,並使用foreach循環創建每個人的地址查詢。由於每個地址查詢創建它被添加到它以後可以使用(填充子節點)的一個TreeView的節點:當從一個linq查詢創建IQueryable時,爲什麼它不是一個「新」變量?

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,然後在每個後續查詢上重寫。這樣做的結果是它就像treenodes中的所有地址查詢都是對最後查詢的引用(?)

進一步的調查,我可以通過使用靜態類來生成地址查詢並通過進入每個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!

回答

5

原因是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 
} 
+0

哇!這是一個難以置信的地獄!謝謝Mehrdad – Calanus 2009-10-16 10:05:12

相關問題