Это действительно возможное исключение InvalidOperationException? - PullRequest
1 голос
/ 16 июля 2010

У меня есть запрос Linq2Sql, который выглядит следующим образом:

var data = from d in dc.GAMEs
    where (d.GAMEDATE + d.GAMETIME.Value.TimeOfDay) >= DateTime.Now
        && d.GAMESTAT == 'O' && d.GAMETYPE == 0 select d;

Resharper подчеркивает «d.GAMETIME.Value.TimeOfDay» синим цветом и говорит, что это возможное исключение System.InvalidOperationException. Хотя я понимаю, что если бы это был код на C #, ссылка на Value без проверки, имеет ли оно значение, была бы такой, я не уверен, верно ли это для запроса Linq.

Фактический сгенерированный SQL выглядит ужасно, и мне хочется сжечь глаза, но я не вижу ничего похожего на пустую ссылку. Могу ли я смело игнорировать это?

(на данный момент игнорировать другие проблемы, например, если он возвращает ожидаемые результаты)

EDIT:

После дальнейших размышлений я вижу, как приведенное выше может вызвать исключение в запросе LinqToObjects и, возможно, другие виды (XML?). Так что да, я думаю, что Решарпер просто в безопасности.

Ответы [ 2 ]

2 голосов
/ 16 июля 2010

При работе с деревьями выражений (как этот запрос LINQ to SQL) это полностью зависит от используемого поставщика LINQ (в вашем случае LINQ to SQL). Таким образом, Решарпер (почти) не может сказать что-нибудь полезное о вашем запросе. Я думаю, что он просто интерпретирует этот код как обычные делегаты C #. Я бы сказал, что это безопасно игнорировать, но, возможно, добавьте комментарий для следующего разработчика.

0 голосов
/ 16 июля 2010

Не видя схемы данных, я предполагаю, что GAMETIME равно Nullable<DateTime> - то есть отображается в поле даты / времени в БД, которое может быть нулевым. Resharper просто выдает предупреждение о статическом анализе, что вы ссылаетесь на Nullable<T>.Value, не проверяя, имеет ли оно значение.

Вы можете переписать запрос следующим образом:

var data = from d in dc.GAMEs
    where (d.GAMEDATE + (d.GAMETIME.HasValue ? d.GAMETIME.TimeOfDay : new TimeSpan())) >= DateTime.Now
        && d.GAMESTAT == 'O' && d.GAMETYPE == 0 select d;

Приведенный выше запрос будет использовать интервал времени 0, если GAMETIME равно NULL.

Учитывая, что GAMEDATE - это необнуляемое поле базы данных, а GAMETIME - обнуляемое, я рекомендую вам сделать GAMETIME также не обнуляемым. Таким образом, два поля являются согласованными и не нуждаются в дополнительной логике для обработки NULL значений.

РЕДАКТИРОВАТЬ Я только что подтвердил, что попытка вызова Nullable<T>.Value действительно выдает InvalidOperationException, а не NullReferenceException.

Из лошадиной пасти (смелость моя):

Два фундаментальных члена Обнуляемая структура - это HasValue Значение свойства. Если HasValue свойство для объекта Nullable правда, значение объекта может быть Доступ к нему осуществляется через свойство Value. Если свойство HasValue имеет значение false, стоимость объекта не определена и попытка получить доступ к значению собственность бросает InvalidOperationException .

...