Тут я працюю зі застарілим кодом, і є багато випадків SqlDataReader
, які ніколи не закриваються та не видаляються. З’єднання закрито, але я не впевнений, чи потрібно керувати пристроєм зчитування вручну.
Чи може це спричинити уповільнення роботи?
Тут я працюю зі застарілим кодом, і є багато випадків 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(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
Заява про використання забезпечить правильне розпорядження об’єктом та звільнення ресурсів.
Якщо ви забудете, тоді ви залишаєте прибирання сміттєзбірнику, що може зайняти деякий час.
Зверніть увагу, що утилізація 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 .