2009-10-16 2 views
2

Entity Framework를 사용하고 있고 People 집합을 보는 루프가 있고 foreach 루프를 사용하면 각 사람의 주소에 대한 쿼리가 만들어집니다.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; 
} 

지금, 나는이 응용 프로그램을 실행에 발견하고 문제가 ALL입니다 : 각 주소 쿼리가 생성되기 때문에 그것은 나중에 (아이 노드를 채우는 데) 사용할 수있는 트 리뷰의 노드에 추가 쿼리는 생성 된 마지막 쿼리 즉 루프의 마지막 반복입니다. 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; 
     } 

} 

내가 가진 문제는 내가이 동작에 의해 당황하고 있다는 점이다. 정적 쿼리 클래스를 사용하는 것이 왜 도움이됩니까? 아무도 내게 무슨 일이 일어 났는지 설명 할 수 있습니까?

혼동 .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

관련 문제