2016-12-14 43 views
3

在以下示例中,我擁有entity1,其中user_id是可爲空的int,有時其實際爲null。 Entity2類似於通過user_id將entity1連接到entity3的橋樑,以獲得person_id並最終得到相應的全名Linq左連接可空字段

我的目標是編寫一個linq查詢,其中如果entity1的user_id爲null,那麼不要拋出NullReferenceException,而是爲fullname屬性獲取null。

考慮下面的實體,我希望我的查詢返回此:

  • codeOfEntity = 「21006.040」,全稱= NULL
  • codeOfEntity = 「14006.010」,全名= 「約翰·史密斯」
  • codeOfEntity = 「21006.020」,全稱= NULL
  • codeOfEntity = 「35716.001」,全名= 「戴維·多伊」
  • codeOfEntity = 「11153.013」,全名= 「扎克白」

實體:

class entity1 
{ 
    public int? user_id { get; set; } 
    public string codeOfEntity { get; set; } 
} 

class entity2 
{ 
    public int user_id { get; set; } 
    public int person_id { get; set; } 
} 

class entity3 
{ 
    public int person_id { get; set; } 
    public string fullname { get; set; } 
} 

,充滿了像:

var listOfEntity1 = new List<entity1>() 
{ 
    new entity1() { user_id = null, codeOfEntity = "21006.040" }, 
    new entity1() { user_id = 10, codeOfEntity = "14006.010" }, 
    new entity1() { user_id = null, codeOfEntity = "21006.020" }, 
    new entity1() { user_id = 1, codeOfEntity = "35716.001"}, 
    new entity1() { user_id = 4, codeOfEntity = "11153.013" } 
}; 

var listOfEntity2 = new List<entity2>() 
{ 
    new entity2() { user_id = 1, person_id = 100 }, 
    new entity2() { user_id = 4, person_id = 400 }, 
    new entity2() { user_id = 10, person_id = 1000 } 
}; 

var listOfEntity3 = new List<entity3>() 
{ 
    new entity3() { person_id = 100, fullname = "John Smith" }, 
    new entity3() { person_id = 400, fullname = "Dave Doe" }, 
    new entity3() { person_id = 1000, fullname = "Zach White" } 
}; 

我查詢拋出一個NullReferenceException:

var result = (from e1 in listOfEntity1 
       join e2 in listOfEntity2 on e1.user_id equals e2.user_id into e2Group 
       from e2 in e2Group.DefaultIfEmpty() 
       join e3 in listOfEntity3 on e2.person_id equals e3.person_id into e3Group 
       from e3 in e3Group.DefaultIfEmpty() 
       select new { e1.codeOfEntity, e3.fullname }).ToList(); 

謝謝。

回答

6

使用C#6.0的空傳播

var result = (from e1 in listOfEntity1 
       join e2 in listOfEntity2 on e1.user_id equals e2.user_id into e2Group 
       from e2 in e2Group.DefaultIfEmpty() 
       join e3 in listOfEntity3 on e2?.person_id equals e3.person_id into e3Group 
       from e3 in e3Group.DefaultIfEmpty() 
       select new { e1.codeOfEntity, e3?.fullname }).ToList(); 

公告中的簡單變化的連接條件,select。將e2.person_id更改爲e2?.person_id,joine3.fullnamee3?.fullname,select

但是,如果你不是在一個位置,使用C#6.0中,這裏是一個另類

var result = (from e1 in listOfEntity1 
       join e2 in listOfEntity2 on e1.user_id equals e2.user_id into e2Group 
       from e2 in e2Group.DefaultIfEmpty() 
       join e3 in listOfEntity3 on (e2==null?-1:e2.person_id) equals e3.person_id into e3Group 
       from e3 in e3Group.DefaultIfEmpty() 
       select new { e1.codeOfEntity, fullname=(e3==null?null:e3.fullname) }).ToList(); 
+1

只是注意,因爲這是一個LINQ到對象的查詢,它會工作。但是,如果處理查詢語句,第一個語句根本無法工作(因爲表達式中不支持空傳播操作符),第二個語句可能會或可能不會運行所有查詢提供程序。在C#6之前,首選的解決方案是爲DefaultIfEmpty()提供一個默認實例作爲參數。 –