Как я могу "отсоединить" SqlDataReader от его объекта SqlConnection? - PullRequest
6 голосов
/ 18 января 2010

У меня есть метод («GetDataReader», давайте его назовем), который возвращает SqlDataReader. Он находится внутри класса Singleton DataFactory, который поддерживает постоянное соединение с базой данных.

Проблема в том, что после возврата DataReader все еще «подключен» к объекту Connection в моей DataFactory. Итак, я должен убедиться, что код, который вызывает GetDataReader, затем вызывает Close () для DataReader, который возвращается, в противном случае он «блокирует» соединение следующим образом:

Уже есть открытый DataReader, связанный с этой командой, который должен быть закрыт первым.

Как я могу "отсоединить" DataReader перед тем, как отправить его обратно из GetDataReader? Или это, или клонировать его и отправить обратно клон? Я не хочу, чтобы вызывающий код всегда явно закрывал его.

Здесь должна быть лучшая практика.

Обновление:

Спасибо всем за ваш вклад. Суть в том, что мне нужно отказаться от привычки использовать DataReaders и переключиться на DataTables. Они намного более управляемы.

Также, спасибо за примечание о пуле соединений. Я знал об этом, но просто не соединил два и два и понял, что заново изобретаю колесо.

Ответы [ 5 ]

6 голосов
/ 18 января 2010

DataReader должны оставаться подключенными к БД, пока они вам больше не понадобятся - такова природа использования DataReader, поэтому вы не можете «отключить» их как таковые. Когда вы закончили работу со считывателем данных, вы должны закрыть его (.Close()), но тогда вы больше не сможете его использовать.

Начиная с .NET 2.0, если вы используете SQL 2005 или более позднюю версию, вы можете использовать MARS (несколько активных наборов результатов), как объяснено здесь . Это позволяет вам использовать одно соединение для нескольких считывателей данных и просто вносит изменения в строку соединения. Однако SqlDataReaders не идеальны для передачи вашего кода так, как вы хотите.

В качестве альтернативы (что, я думаю, вам нужно сделать), вы можете использовать отключенный набор результатов, в который входят DataSet / DataTables. Вы используете SqlDataAdapter для заполнения DataSet / DataTable все результаты запроса. Затем вы можете использовать соединение для любых других целей или закрыть соединение, и это не повлияет на ваш набор результатов в памяти. Вы можете передавать свой набор результатов по своему коду без необходимости поддерживать открытое соединение с базой данных.

2 голосов
/ 18 января 2010

Не сохраняйте соединение с базой данных. Существует функция под названием «пул соединений». Получение свежего соединения не дорого.

1 голос
/ 18 января 2010

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

0 голосов
/ 23 ноября 2017

Вот удобный вспомогательный метод для выполнения некоторого SQL для соединения и отключения его от сервера:

public static DbDataReader ExecuteReaderClient(DbConnection connection, DbTransaction transaction, String commandText)
{
    DbCommand command = connection.CreateCommand();
    command.CommandText = commandText;
    if (transaction != null)
        command.Transaction = transaction;

    DbDataAdapter adapter = DbProviderFactories.GetFactory(connection).CreateDataAdapter();

    adapter.SelectCommand = command;
    DataSet dataset = new DataSet();

    try
    {
        adapter.Fill(dataset);
    }
    catch (Exception e)
    {
        throw new Exception(
                  e.Message + "\r\n" +
                  "Command Text" + "\r\n" +
                  commandText, e);
    }

    try
    {
        return dataset.CreateDataReader();
    }
    finally
    {
        dataset.Dispose();
    }
}
0 голосов
/ 18 января 2010

Я думаю, что вы, возможно, перепутали свои наборы данных (отключенные внедренные данные) и устройства чтения данных (без данных). DataReader без SqlCnnection - это ... ммм ... просто считыватель, т.е. нет данных; -)

Я думаю, что ваша проблема еще выше в вашем мышлении. Я предполагаю, что вы программист старой школы, привыкший делать все вручную. В «управляемом» мире точечной сети многие вещи управляются для вас; ADO.NET уже имеет эффективную систему пула подключений к данным, вам не нужно поддерживать свой собственный пул.

-Oisin

...