Необходимо ли вручную закрыть и утилизировать SqlDataReader?
Я работаю с устаревшим кодом здесь и есть много экземпляров SqlDataReader
которые никогда не закрываются и не утилизируются. Соединение закрыто, но я не уверен, Нужно ли управлять читателем вручную.
может ли это вызвать замедление производительности?
4 ответа:
старайтесь избегать использования читателей, как это:
SqlConnection connection = new SqlConnection("connection string"); SqlCommand cmd = new SqlCommand("SELECT * FROM SomeTable", connection); SqlDataReader reader = cmd.ExecuteReader(); connection.Open(); if (reader != null) { while (reader.Read()) { //do something } } reader.Close(); // <- too easy to forget reader.Dispose(); // <- too easy to forget connection.Close(); // <- too easy to forget
вместо этого оберните их с помощью операторов:
using(SqlConnection connection = new SqlConnection("connection string")) { connection.Open(); using(SqlCommand cmd = new SqlCommand("SELECT * FROM SomeTable", connection)) { using (SqlDataReader reader = cmd.ExecuteReader()) { if (reader != null) { while (reader.Read()) { //do something } } } // reader closed and disposed up here } // command disposed here } //connection closed and disposed here
оператор using обеспечит правильную утилизацию объекта и освобождение ресурсов.
Если вы забыли, то вы оставляете уборку до сборщика мусора, который может занять некоторое время.
обратите внимание, что удаление экземпляра SqlDataReader выполняется с помощью SqlCommand.ExecuteReader () will не закрыть / удалить базовое соединение.
есть две общие закономерности. В первом читатель открывается и закрывается в пределах области соединения:
using(SqlConnection connection = ...) { connection.Open(); ... using(SqlCommand command = ...) { using(SqlDataReader reader = command.ExecuteReader()) { ... do your stuff ... } // reader is closed/disposed here } // command is closed/disposed here } // connection is closed/disposed here
иногда удобно иметь метод доступа к данным открыть соединение и вернуть считыватель. В этом случае важно, чтобы возвращенный читатель был открыт с помощью Метода commandbehavior.CloseConnection, так что закрытие / удаление читателя закроет базовое соединение. Картина выглядит примерно так:
public SqlDataReader ExecuteReader(string commandText) { SqlConnection connection = new SqlConnection(...); try { connection.Open(); using(SqlCommand command = new SqlCommand(commandText, connection)) { return command.ExecuteReader(CommandBehavior.CloseConnection); } } catch { // Close connection before rethrowing connection.Close(); throw; } }
и вызывающий код просто должен расположить читателя таким образом:
using(SqlDataReader reader = ExecuteReader(...)) { ... do your stuff ... } // reader and connection are closed here.
чтобы быть в безопасности, оберните каждый объект SqlDataReader в используя заявлением.