Будет ли dataReader оставаться нулевым, вызывая неверную попытку вызова метаданных, когда читатель закрыт?

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

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

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


person shashi    schedule 07.04.2011    source источник


Ответы (2)


Как только блок использования заканчивается, устройство чтения данных закрывается. Таким образом, любая попытка прочитать данные из считывателя вызовет исключение. Помните, что устройство чтения данных использует соединение с базой данных. Когда соединение закрыто (после вашего использования оператора), это вызовет 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
 }

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

person JonH    schedule 07.04.2011
comment
Но dataReader был объявлен за пределами используемого блока. Скорее он был объявлен снаружи и передан этому методу. - person shashi; 07.04.2011
comment
@sassyboy - это не имеет значения, потому что вы используете соединение sqlConnection в своем командном объекте. И ваш командный объект, который использует ваш объект sqlConnection, используется для .ExecuteReader. Это означает, что ваш считыватель данных использует ваш объект sqlConnection. Итак, что происходит, так это то, что сразу после оператора using объект sqlConnection удаляется, что означает, что ваш командный объект завершен, и ваш считыватель данных завершен. - person JonH; 07.04.2011