Будет ли dataReader оставаться нулевым, что приведет к «Неверной попытке вызвать MetaData, когда читатель закрыт»? - PullRequest
1 голос
/ 07 апреля 2011

Я написал этот метод, чтобы мне не приходилось каждый раз писать открывающее соединение и т. Д.

 public static bool TryExecuteReader(string commandText,string functionNameForLogging, string errorText, out SqlDataReader dataReader)
        {
            bool success = false;
            dataReader = null;
            try
            {
                using (SqlConnection sqlConnection = SqlUtilities.CreateSqlConnection())
                {
                    sqlConnection.Open();
                    SqlCommand sqlCommand = sqlConnection.CreateCommand();
                    sqlCommand.CommandText = commandText;
                    dataReader = sqlCommand.ExecuteReader(CommandBehavior.CloseConnection);                    
                }
                success = true;
            }
            catch (Exception ex)
            {
                SqlUtilities.LogError(functionNameForLogging,ex.Message,-1);
            }

            return success;
        }

Я думал, что это должно работать нормально, но в последнее время я получаю сообщение об ошибке "Недопустимая попытка вызова метаданных, когда читатель закрыт". Теперь я не уверен, почему эта ошибка происходит. Но это казалось наиболее вероятной причиной. Прошло какое-то время, поэтому я не могу точно сказать, вызвана ли ошибка этим способом. после того, как закончится использование блока, устройство чтения данных останется нулевым?

Ответы [ 2 ]

1 голос
/ 07 апреля 2011

Прочтите сообщение: ExecuteReader с CommanBehavior (автоматически закрывает соединение после чтения данных)

Вы получаете сообщение об ошибке, потому что закрываете соединение при использовании блока USING.

Вместо этого набора команд поведения

  • CommandBehavior.CloseConnection

    Когда вы передаете вышеуказанные значения в качестве аргумента в ExecuteReader

    1. нет необходимости явно закрывать соединение, соединение закрывается при закрытии считывателя.

      // Нет необходимости закрывать соединение, вам просто нужно написать reader.Close ();

    2. Это полезно, когда вы передаете считыватель другому методу для обработки данных.

1 голос
/ 07 апреля 2011

Как только блок использования завершается, устройство чтения данных закрывается. Таким образом, любая попытка чтения данных из устройства чтения приведет к исключению. Помните, что для чтения данных используется соединение БД. Когда соединение закрывается (после вашего оператора using), это в свою очередь вызывает Dispose для SQLConnection, что делает SqlDataReader ничем / нулем.

Поместите свой код для создания соединения вне оператора using, вот так.

SqlConnection sqlConnection = SqlUtilities.CreateSqlConnection()
using(SqlCommand sqlCommand = sqlConnection.CreateCommand())
 {
  sqlCommand.CommandText = commandText; 
  dataReader = sqlCommand.ExecuteReader   (CommandBehavior.CloseConnection);                     
 }
conn.Open();
success=true;

Поскольку вы указали:

CommandBehavior.CloseConnection

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

Вы можете, если хотите, чтобы ваша функция возвращала заголовок данных вместо логического. Это действительно зависит от ваших предпочтений. Но если вы вернете устройство чтения данных, вы можете проверить с помощью методов HasRows или Read. Затем вы можете обернуть источник данных в оператор using, например:

using (SqlDataReader myDataReader = GetMyDataReader())
 {
   //do something with the reader
 }

В конце оператора using для myDataReader .Dispose() будет вызван автоматически. Поскольку вы набрали .ExecuteReader() внутри GetMyDataReader() с CommandBehavior.CloseConnection, то утилита считывателя также закроет ваше соединение с БД.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...