2011-10-15 261 views
0

我有以下代碼LINQ查詢返回空結果

nodes = data.Descendants(XName.Get("{http://schemas.microsoft.com/LiveSearch/2008/04/XML/web}Results")).Nodes(); 
     System.Collections.Generic.IEnumerable<Result> res = new List<Result>(); 
     if (nodes.Count() > 0) 
     { 
      var results = from uris in nodes 
          select new Result 
     { 
      URL = 
((XElement)uris).Element(XName.Get("{http://schemas.microsoft.com/LiveSearch/2008/04/XML/web}Url")).Value, 
      Title = 
((XElement)uris).Element(XName.Get("{http://schemas.microsoft.com/LiveSearch/2008/04/XML/web}Title")).Value, 
      Description = 
((XElement)uris).Element(XName.Get("{http://schemas.microsoft.com/LiveSearch/2008/04/XML/web}Description")).Value, 
      DateTime = 
((XElement)uris).Element(XName.Get("{http://schemas.microsoft.com/LiveSearch/2008/04/XML/web}DateTime")).Value, 
     }; 
      res = results; 
     } 

如果結果是誰擁有這些URL一個對象,標題,描述和日期時間變量的定義。

這一切都正常工作,但是當節點中的'節點'不包含描述元素(或至少我認爲多數民衆贊成什麼投擲它)程序命中「res =結果;」 一行代碼並拋出「對象引用未設置爲...」錯誤,並在「選擇新結果」後突出顯示整個部分。

如何解決此問題?

回答

3

最簡單的方法是投射到string而不是使用Value屬性。這樣你最終會得到一個null參考Description

然而,你的代碼也可以做成一個很多更好:

XNamespace ns = "http://schemas.microsoft.com/LiveSearch/2008/04/XML/web"; 

var results = data.Descendants(ns + "Results") 
        .Elements() 
        .Select(x => new Result 
          { 
          URL = (string) x.Element(ns + "Url"), 
          Title = (string) x.Element(ns + "Title"), 
          Description = (string) x.Element(ns + "Description"), 
          DateTime = (string) x.Element(ns + "DateTime") 
          }) 
        .ToList(); 

見該是多麼簡單得多?若干技術問題探討使用:

  • 上一個空序列調用ToList()給你反正
  • 這樣你就永遠只能執行一次查詢列表;在你打電話Count()之前,它可能已經迭代了每個節點。一般來說,使用Any()而不是Count() > 0) - 但這次只是讓列表無條件更簡單。
  • 使用Elements()方法獲取子元素,而不是多次投射。 (您前面的代碼會拋出一個異常,如果它遇到的任何非元素節點)
  • 使用從字符串隱式轉換爲XNamespace
  • 使用+(XNamespace, string)運營商獲得一個XName
+0

問題依然存在..也許它不是從節點丟失的元素。有沒有一種方法可以用不同的方式來添加「保護措施」? – Ryan

+0

@Ryan:嘗試我的替代(更簡單)的代碼,如果仍然失敗,請編輯一個簡短的* complete *程序(包括XML)到您的問題中,以便我們可以看到發生了什麼。 –

+0

這種更好的編寫代碼的方式避免了這個問題..非常感謝Jon – Ryan

1

如果說明元素不包括你應該測試這個

((XElement)uris).Element(XName.Get("{http://schemas.microsoft.com/LiveSearch/2008/04/XML/web}Description")) 

在使用Value之前不爲空。試試這個代碼:

var results = from uris in nodes let des = ((XElement)uris).Element(XName.Get("{http://schemas.microsoft.com/LiveSearch/2008/04/XML/web}Description")) 
         select new Result 
    { 
     URL = ((XElement)uris).Element(XName.Get("{http://schemas.microsoft.com/LiveSearch/2008/04/XML/web}Url")).Value, 
     Title = ((XElement)uris).Element(XName.Get("{http://schemas.microsoft.com/LiveSearch/2008/04/XML/web}Title")).Value, 
     Description = (des != null) ? des.Value : string.Empty, 
     DateTime = ((XElement)uris).Element(XName.Get("{http://schemas.microsoft.com/LiveSearch/2008/04/XML/web}DateTime")).Value, 
    };