Как использовать linq2Xml без возможности нулевого исключения? - PullRequest
4 голосов
/ 15 ноября 2009

Я написал этот простой запрос linq-to-xml, и кажется, что с помощью синтаксиса linq нельзя избежать нулевого исключения. Я использую это неправильно? Каким должен быть правильный (и короткий) синтаксис Linq2Xml?

Запрос linq2Xml

var userData =
    queryUserResponseData.Elements("user")
        .Single(u => u.Element("username").Value == userName);

XML

<data>
    <user>
        <username>User1</username>
        <userid>123</userid>
    </user>
    <user>
        <username>User2</username>
        <userid>456</userid>
    </user>
    <user>
        <userid>999</userid>
    </user>
</data>

Ответы [ 5 ]

5 голосов
/ 15 ноября 2009

XElement и XAttribute имеют некоторые явные операторы преобразования для преобразования их значения в определенные типы. Они так полезны, потому что возвращают ноль, если Элемент или Атрибут отсутствуют.

var userData = queryUserResponseData.Elements("user").Single(u => (string)u.Element("username") == userName);
2 голосов
/ 15 ноября 2009

Из вашего комментария к ответу Ахмада Магида:

Проблема на самом деле в u.Element("username").Value, когда Resharper уведомляет меня о возможном нулевом исключении

похоже, вы беспокоитесь о потенциальной, а не о реальной проблеме. Вы знаете, что ваши данные будут означать, что вы всегда будете возвращать 1 результат, однако ReSharper не имеет доступа к вашим данным, поэтому он подчеркивает тот факт, что если бы результатов не было, он генерировал бы исключение нулевой ссылки.

Вы можете сделать одну из трех вещей:

  1. Игнорировать предупреждение и ничего не делать.

  2. Перекодируйте, чтобы учесть это, чтобы исключить вероятность исключения (см. Другие ответы).

  3. Оберните Linq в try {} catch {}, чтобы, если произойдет «немыслимое», ваша программа не вылетит.

Только вы действительно можете решить, что вы хотите сделать.

1 голос
/ 15 ноября 2009

Согласно вашему комментарию к ответу Ахмада, я предполагаю, что вы получаете NullReferenceException, когда элемент не имеет узла.Вы можете исправить это следующим образом -

var userData =
    doc.Elements("user")
    .Single(u => u.Element("username") != null && u.Element("username").Value == userName);

Но если DTD или XSD требуется узел имени пользователя там, или вы уверены, что все элементы будут иметь узел имени пользователя, вы можете просто проигнорировать предупреждение ReSharper.

1 голос
/ 15 ноября 2009

Использование Single означает, что вы ожидаете, что будет ровно 1 результат. Когда возвращается больше результатов, Single выдаст исключение. Вы можете использовать First для получения первого элемента или Last для последнего. Для нескольких элементов вы хотите просмотреть результаты и получить к ним доступ по отдельности.

Если нет соответствующего результата, вы можете использовать SingleOrDefault для возврата значения null или значения по умолчанию используемого типа.

Является ли queryUserResponseData XElement или XDocument? Если это XDocument, вам сначала нужно получить доступ к корню XML, например:

var userData = queryUserResponseData.Root.Elements("user")
                 .Single(u => u.Element("username").Value == userName);

Кроме того, поиск User1 или User2 в вашем примере будет работать. Однако, если вы искали User3 , которого не существует, Single выдаст исключение. В этом случае вы должны использовать SingleOrDefault:

var userData = queryUserResponseData.Elements("user")
                 .SingleOrDefault(u => u.Element("username").Value == "User3");
0 голосов
/ 15 ноября 2009
var userData = queryUserResponseData.Elements("user")
    .Select(u => u.Element("username"))
    .Where(uNode => uNode != null)
    .Single(uName => uName.Value == userName);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...