Когда SqlCommand.ExecuteReader() возвращает null?

При использовании метода SqlCommand.ExecuteReader() ReSharper сообщает мне, что у меня есть возможное исключение NullReference, когда я потом использую объект SqlDataReader.

Итак, со следующим кодом:

using (SqlConnection connection = GetConnection())
{
    using (SqlCommand cmd = connection.CreateCommand())
    {
        cmd.CommandText = ; //snip

        using (SqlDataReader reader = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                //snip
            }
        }
    }
}

Строка while (reader.Read()) подчеркнута.

Мой вопрос в том, когда объект-читатель будет иметь значение null? Я никогда не сталкивался с этим, и в документации не упоминается, что это может быть. Должен ли я проверять, является ли оно нулевым или безопасно ли игнорировать?

И почему ReSharper думает, что это может быть null, когда, например, он позволяет мне использовать SqlCommand, не рекомендуя его проверять на нуль? Я предполагаю, что есть атрибут метода ExecuteReader.

Ответ 1

Это ложное срабатывание.

Отражая SqlDataReader.ExecuteReader, я вижу, что единственный способ, которым читатель возвращается как null, - это если внутренний метод RunExecuteReader передан 'false' для returnStream, а это не так.

В глубине SqlDataReader конструктор чтения a всегда вызывается в какой-то момент, поэтому я уверен, что для ExecuteReader физически невозможно вернуть null.

Ответ 2

Resharper верен, он может возвращать нулевой потенциал.

Не имеет значения, не позволяет ли конкретная реализация для ExecuteReader() выпустить нулевое значение - факт остается фактом, что IDataReader - это объект, который может содержать (или указывать) значение null.

  • Что делать, если в будущем вы решите использовать другую реализацию IDbCommand?
  • Что делать, если следующее обновление этой реализации IDbCommnd будет содержать другой поток в коде, который позволит пузырить нулевое значение?

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

Ответ 3

У меня была эта проблема с ними в нескольких других областях. Кажется, они провели анализ путей кода в различных частях CLR. Когда они находят, что возможно вернуть null, это когда они жалуются на это.

В конкретном случае, о котором я жаловался, null не мог на самом деле произойти. Тем не менее, они проследили график вызовов до метода, который в некоторых случаях мог бы возвращать значение null, и нулевое значение могло бы распространяться в верхней части.

Итак, я называю это ошибкой ReSharper (думаю, я ранее называл ее ошибкой CLR).

Ответ 4

Я определил одну причину, по которой ExecuteReader() может вернуть значение null.

В случае, когда я получал нуль, я отправил моему клиенту script для обновления хранимой процедуры. Мой клиент Sql Server (2000) настроен так, чтобы пользователям БД требовалось разрешение на выполнение хранимой процедуры. Когда они обновили SP, разрешение было удалено и не было повторно назначено. В этом случае SqlCommand.ExecuteReader() вернул нуль.

Повторное присвоение разрешения исправлено.

Ответ 5

У меня возникла проблема, когда я запросил .dbo.sysfiles для лог файлов и получил null взамен. Я подключил своего клиента к пользователю SYSTEM, который был сисадмином, но не уверен, что произошло...