2011-10-15 215 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, 
    };