2015-01-12 3 views
0

첫 번째 테이블을 CustID 열에서 두 번째 테이블에 두 번 LEFT 조인되도록 두 DataTable 조인하려고합니다. 첫 번째 플랜트 테이블은 동물 테이블의 PlantID와 일치해야하며 조인의 두 번째 플랜트 테이블은 동물 테이블의 PlantID와 일치해서는 안됩니다. 그러나 Linq에서 이것을 시도하면 where 절을 모두 무시하는 것처럼 보입니다.여러 왼쪽 조인 및 Linq 같음 및 같음 결합

동물 :

ID | CustID | PlantID 
===================== 
1 | 1 | <null> 
2 | 2 | 1 
3 | 2 | <null> 

식물 :

ID | CustID | Name 
================== 
1 | 2 | b1 
2 | 2 | b2 

가 SQL에서 내가 원하는 쿼리가 될 것이다 : 데이터 세트에 LINQ로를 시도 할 때 다음

SELECT a.id, a.custid, p1.id AS PlantID1, p2.id AS PlantID2 
FROM  animals a 
LEFT JOIN plants p1 on a.custid = p1.custid AND a.plantid = p1.id 
LEFT JOIN plants p2 on a.custid = p2.custid AND a.plantid != p2.id 

내 코드입니다 :

 DataTable animals = new DataTable(); 
     animals.Columns.Add("id", typeof(int)); 
     animals.Columns.Add("custid", typeof(int)); 
     animals.Columns.Add("plantid", typeof(int)); 
     animals.Rows.Add(1, 1, DBNull.Value); 
     animals.Rows.Add(2, 2, 1); 
     animals.Rows.Add(3, 2, DBNull.Value); 

     DataTable plants = new DataTable(); 
     plants.Columns.Add("id", typeof(int)); 
     plants.Columns.Add("custid", typeof(int)); 
     plants.Columns.Add("name", typeof(string)); 
     plants.Rows.Add(1, 2, "b1"); 
     plants.Rows.Add(2, 2, "b2"); 

     var test = from al in animals.AsEnumerable() 
        join bl in plants.AsEnumerable() 
        on new { x = al["custid"], y = al["plantid"] } equals new { x = bl["custid"], y = bl["id"] } into gj 
        join bl2 in plants.AsEnumerable() 
        on al["custid"] equals bl2["custid"] into gj2 
        from subbl in gj.DefaultIfEmpty() 
        from subbl2 in gj2.DefaultIfEmpty() 
        select new 
        { 
         aid = al["id"], 
         custid = al["custid"], 
         plantid1 = subbl == null ? DBNull.Value : subbl["id"], 
         plantName = subbl == null ? DBNull.Value : subbl["name"], 
         plantid2 = subbl2 == null ? DBNull.Value : subbl2["id"], 
         plantName2 = subbl2 == null ? DBNull.Value : subbl2["name"] 
        }; 
     var result = test.Where(st => st.plantid1 != st.plantid2).Cast<object>().ToList(); 

결과 내가 할 내가 어디 절에 의해 제외 될 것이라고 생각 다음 행이 포함

aid | custid | plantid1 | plantid2 
================================== 
1 | 1 | 
2 | 2 | 1  | 1 
2 | 2 | 1  | 2 
2 | 2 |   | 1 
2 | 2 |   | 2 

내가 개체에 대한 LINQ와 함께 그것을 시도, 두 번째 행은 내가 기대하는, 존재하지 않는 . 다음은 객체를 사용하는 코드입니다.

class animal 
    { 
     public int id, custid; 
     public int? plantid; 
    } 
    class plant 
    { 
     public int id; 
     public int custid; 
     public string name; 
    } 
    List<object> testStructs() 
    { 
     List<animal> animals = new List<animal>() 
     { 
      new animal() { id = 1, custid = 1, plantid = 0 }, 
      new animal() { id = 2, custid = 2, plantid = 1 }, 
      new animal() { id = 3, custid = 2 } 
     }; 
     List<plant> plants = new List<plant>() 
     { 
      new plant() { id = 1, custid = 2, name = "col1" }, 
      new plant() { id = 2, custid = 2, name = "col2" } 
     }; 
     var test = from al in animals.AsEnumerable() 
        join bl in plants.AsEnumerable() 
        on new { x = al.custid, y = al.plantid } equals new { x = bl.custid, y = (int?)bl.id } into gj 
        join bl2 in plants.AsEnumerable() 
        on al.custid equals bl2.custid into gj2 
        from subbl in gj.DefaultIfEmpty() 
        from subbl2 in gj2.DefaultIfEmpty() 
        select new 
        { 
         aid = al.id, 
         custid = al.custid, 
         plantid1 = subbl == null ? null : (int?)subbl.id, 
         plantName = subbl == null ? string.Empty : subbl.name, 
         plantid2 = subbl2 == null ? null : (int?)subbl2.id, 
         plantName2 = subbl2 == null ? string.Empty : subbl2.name 
        }; 

     return test.Where(st => st.plantid1 != st.plantid2 || st.plantid1 == null || st.plantid2 == null).Cast<object>().ToList(); 
    } 

답변

0

내가 잘못하고있는 것을 해결했습니다. 내 where 절은 참조로 비교되는 익명 형식의 필드를 비교합니다. where 절은 해당 필드의 값을 비교하려면

Where(st => !st.plantid1.Equals(st.plantid2)) 

이어야합니다.