2012-04-27 22 views
2

使用C#和LINQ到實體我有孩子和家長實體搜索的問題。在概念上,我試圖讓孩子們的IEnumerable當這些孩子有一定的特性以及這些孩子的父母有一定的屬性的集合。LINQ到實體子查詢,其中母公司有一定的性能

具體而言我有路線和街道上有一個多對多的關係。我試圖找到街道上,其中有街或LeftNote的RightNote積極性的具體路線(LeftNote和RightNote是字符串,我正在尋找不屬於空白字符串)。

我有以下實體(上剪下來的清晰度)

public class Route 
{ 
    public int RouteID { get; set; } 

    public virtual ICollection<Street> Streets { get; set; } 
} 

public class Street 
{ 
    public string LeftNote { get; set; } 

    public string RightNote { get; set; } 

    public virtual ICollection<Route> Routes { get; set; } 
} 

我有以下的LINQ表達式:

var streets = this.repository.Routes 
         .Where(r => r.RouteID == routeId).FirstOrDefault() 
         .Streets 
         .Where(s => s.LeftNote.Length > 0 || s.RightNote.Length > 0); 

這工作完全直到我跑這對實體數據,在此路由存在但是沒有擁有LeftNotes或RightNotes的街道。在這些情況下,我得到一個NullReference異常。我試圖找到一種方法來正確表達這個查詢處理與LeftNotes街道的缺席(應始終存在一個匹配routeId的路由,如果不是這是一個有效的異常情況,應該拋出和錯誤)。

編輯:這個問題似乎是圍繞空字符串,而不是任何有關LINQ的構建。

回答

1

你實際上意味着

var streets = repository.Streets.Where 
     (s => s.Routes.Any(r => r.RouteID == routeId) 
      && (s.LeftNote.Length > 0 || s.RightNote.Length > 0)); 
+1

路由沒有LeftNote和RightNote,而是Streets擁有它們。 – Marshal 2012-04-27 11:08:15

+0

我會按照你所描述的測試 – AlexC 2012-04-27 17:07:54

0

請嘗試以下方法:

var streets = this.repository.Routes 
          .Where(r => r.RouteID == routeId).FirstOrDefault() 
          .Streets 
          .Where(s => s.LeftNote ? s.LeftNote.Length > 0 : false || s.RightNote ? s.RightNote.Length > 0 : true); 

更新

var streets = this.repository.Streets 
          .Where(s => s.Routes.RouteID == routeId && s.LeftNote.Length > 0 || s.RightNote.Length > 0); 

更新代碼中插入新的代碼之後。

使用假第一的原因是爲了迫使第二或條款的驗證。不確定以下是否有效。

+0

@Flowerking:對不起,我要把'',而不是''???感謝您指出這一點。我更新了我的代碼。 – sarwar026 2012-04-27 11:02:46

+0

這不會編譯,因爲您試圖在s.LeftNote中將字符串賦給false的布爾值? s.LeftNote.Length> 0:false和s.RightNote中布爾值爲true的字符串? s.RightNote.Length> 0:true。我對你可能暗示的解決方案感興趣,但就目前情況來看,這對我來說並不合理。 – AlexC 2012-04-27 11:06:38

+0

'將一個字符串賦值給布爾值'那是怎麼回事? 's.LeftNote.Length> 0'是一個布爾值,所以'false'是。我不明白,請澄清 – sarwar026 2012-04-27 11:09:55

1
var streets = this.repository 
        .Routes 
        .Where(r => r.RouteID == routeId).FirstOrDefault() 
        .Streets 
        .Where(s => s.LeftNote !=null ? s.LeftNote.Length > 0 : false 
          || s.RightNote !=null ? s.RightNote.Length > 0 : false); 

沒有帶測試,但認爲它應該工作。

OR

this.repository.Streets(s=>(s.LeftNote.Length >0 || s.RightNote.Length > 0) 
          && s.Routes.routeId==routeId)); 
+0

第一個選項編譯並執行,但是與我想要的相反(它返回路線上的所有街道而不考慮關係)。第二個選項需要找到遍歷路線集合。 Routes.routeId不合法。 – AlexC 2012-04-27 11:26:14

+0

將這兩個返回值設置爲'false',它現在應該可以工作。 (請參閱編輯) – Marshal 2012-04-27 11:34:29

0

它有沒有在一個查詢

IEnumerable<Street> streets = Enumerable.Empty<Street>(); 
var route = this.repository 
       .Routes 
       .Where(r => r.RouteID == routeId).FirstOrDefault() 

if(route != null && route.Streets.Any()) 
{ 
    streets = route.Streets 
        .Where(s => s.LeftNote.Length > 0 
          || s.RightNote.Length > 0); 
} 
1

要執行只需使用String.IsNullOrEmpty()。

var streets = this.repository 
       .Routes 
       .Where(r => r.RouteID == routeId).FirstOrDefault() 
       .Streets 
       .Where(s => !String.IsNullOrEmpty(s.LeftNote) || 
          !String.IsNullOrEmpty(s.RightNote)); 
+0

這似乎工作,我需要進一步測試 – AlexC 2012-04-27 11:41:09

+0

@AlexC FirstOrDefault實現查詢,因此該部分之前運行在服務器上(在SQL中),該部分在本地運行後。您可以通過在服務器上運行整個查詢來提高效率(如有必要)。 – Phil 2012-04-27 12:46:42

+0

@菲爾,你會怎麼建議去做這件事? – AlexC 2012-04-27 13:44:07

0

嘗試改變LINQ表達這個

var streets = this.repository.Routes 
        .Where(r => r.RouteID == routeId).FirstOrDefault() 
        .Where(r => r.Streets.Any(s => s.LeftNote.Length > 0 || s.RightNote.Length > 0));