Здесь я работаю с устаревшим кодом, и многие его экземпляры SqlDataReader
никогда не закрываются и не удаляются. Соединение закрыто, но я не уверен, нужно ли управлять считывателем вручную.
Может ли это вызвать снижение производительности?
Старайтесь избегать использования таких читателей:
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:
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 (), не приведет к закрытию / удалению базового соединения.
Есть два общих шаблона. В первом случае считыватель открывается и закрывается в рамках соединения:
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.
источник
using
s, тогда вызовите dispose вfinally {}
блоке после catch. Как это написано, успешные команды никогда не будут закрыты или удалены.На всякий случай оберните каждый объект SqlDataReader в оператор using .
источник
Просто оберните ваш SQLDataReader оператором using. Это должно решить большинство ваших проблем.
источник