Как Dispose вызывается на объектах ADO.NET? - PullRequest
2 голосов
/ 13 апреля 2011

Классы доступа к базе данных, которые реализуют IDbConnection, IDbCommand и IDataReader, все реализуют IDisposable, но, очевидно, Команда и Считыватель зависят от Соединения.У меня вопрос, должен ли я Dispose () каждого из этих объектов по отдельности, или утилизация объекта Connection избавится от других?

То есть, могу ли я сделать это и гарантировать, что я не рискну оставить неуправляемые ресурсы неосвобожденными:

using (IDbConnection conn = GetConnection())
{
      IDbCommand cmd = conn.CreateCommand();
      cmd.CommandText = " ..... ";
      IDataReader rdr = cmd.ExecuteReader();
      while (rdr.Read())
      {

      }
}

Или я должен сделать это вместо этого:

using (IDbConnection conn = GetConnection())
{
    using (IDbCommand cmd = conn.CreateCommand())
    {
        cmd.CommandText = " ..... ";
        using (IDataReader rdr = cmd.ExecuteReader())
        {
            while (rdr.Read())
            {

            }
        }
    }
}

Или это зависит от реализации, поэтому она может работать с использованием одного поставщика базы данных, но не другого?

Ответы [ 5 ]

4 голосов
/ 13 апреля 2011

Лучшая политика - использовать все объекты ADO.NET при использовании блоков - полная остановка.

Небольшое отражение на различных объектах ADO.NET показывает, что вещи будут более или менее сброшены на пол, если не будут закрыты / уничтожены. Эффект от этого во многом будет зависеть от того, каких провайдеров вы используете - если вы используете что-то с неуправляемыми дескрипторами внизу (ODBC, OleDb и т. Д.), Вы, вероятно, потеряете память, поскольку я ничего не видел на пути финализаторов. Если это полностью управляемый поставщик (например, SqlClient), он в конечном итоге будет очищен, но в зависимости от того, какие объекты вы держите, вы можете в конечном итоге сохранить ресурсы на сервере БД намного дольше, чем вы хотите .

1 голос
/ 13 апреля 2011

Утилизируйте их по отдельности. Вполне возможно, что объекты Reader и Command делают больше в своих процедурах удаления, чем просто разрушают соединение (либо сейчас, либо в будущей версии ADO.NET). Таким образом, чтобы (а) быть явным и (б) быть безопасным, вы должны распоряжаться ими в индивидуальном порядке.

Тот факт, что они реализуют IDisposable, предполагает, что вы всегда должны запускать процедуру Dispose, когда закончите работу с объектом, поэтому лучше не пытаться угадать интерфейс, это не даст вам никакой пользы, и вы Вероятно, в конечном итоге утечка памяти и ручек.

Есть вещи, которые вы можете сделать, чтобы ваш код выглядел чище при вложении using операторов. Например:

(using SqlConnection conn = new SqlConnection())
(using SqlCommand comm = new SqlCommand())
{
    //Do stuff
}

Это выглядит аккуратнее (на мой взгляд), чем вложение скобок.

1 голос
/ 13 апреля 2011

Вы должны распоряжаться ими по отдельности, или вы также можете использовать решение, предоставленное здесь .

0 голосов
/ 13 апреля 2011

Основным преимуществом оператора использования является управление высвобождением ресурсов.Обычно .NET Framework Garbage Collector контролирует распределение и освобождение ресурсов.С помощью оператора using мы можем взять его под контроль.Таким образом, оператор using реализует интерфейс IDisposible, который содержит открытый метод Dispose ().

Также вы всегда можете вызвать метод Dispose () вручную, чтобы освободить ресурс или объект из памяти.надеюсь это поможет.

0 голосов
/ 13 апреля 2011

Вы должны распоряжаться ими индивидуально. Даже если удаление IDbConnection приведет к удалению всего под покровом (я не знаю, действительно ли это происходит, и меня это не волнует по следующей причине), вам следует программировать в будущем времени. Завтра кто-то отредактирует этот код и выдаст новую команду для того же соединения, а затем спросит, почему он получает ошибку, что соединение все еще используется (потому что IDataReader не был удален).

...