LINQ-запрос, возвращающий нулевые результаты - PullRequest
0 голосов
/ 15 октября 2011

У меня есть следующий код

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;
        }

Где Results - это объект, для которого определены переменные URL, Title, Description и DateTime.

Все это нормально работает, но когда «узел» в узлах не содержит элемент Description (или, по крайней мере, я думаю, что это бросает его), программа нажимает «res = results;»строка кода и выдает ошибку 'ссылка на объект не установлена ​​на ...' и выделяет весь раздел сразу после "выберите новые результаты" ..

Как это исправить?

Ответы [ 2 ]

3 голосов
/ 15 октября 2011

Самый простой способ - привести к 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
1 голос
/ 15 октября 2011

Если элемент Description не включен, вы должны проверить, если это

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

не равно нулю перед использованием значения. Попробуйте этот код:

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,
    };
...