Вопрос

Я пытался объяснить кому-то, почему Соединения с базой данных Реализуйте idisposable, когда я понял, что я действительно знаю, что «открытие соединения» на самом деле означает.
Так что мой вопрос - что делает C # практически, когда он открывает связь?

Спасибо.

Это было полезно?

Решение

Существует на самом деле два класса, участвующие в реализации соединения (на самом деле больше, но я упрощает).

Один из них - это IDbConnection реализация (SQLConnection, NpgsqlConnection, OracleConnection, и т. Д.) Что вы используете в своем коде. Другой - это «реальный» объект подключения, который является внутренним для сборки, и не видно для вашего кода. Мы назовем этоRealConnection«На данный момент, хотя его фактическое имя отличается с разными реализациями (например, в NPGSQL, в котором есть тот случай, когда я больше всего знаком с реализацией, класс называется NpgsqlConnector).

Когда вы создаете свой IDbConnection, у него нет RealConnection. Отказ Любая попытка сделать что-то с базой данных. Когда ты Open() Тогда происходит следующее:

  1. Если объединение включено, и есть RealConnection в бассейне, укажите это и сделайте это RealConnection для IDbConnection.
  2. Если объединение включено, и общее количество RealConnection Объекты, существующие больше, чем максимальный размер, бросают исключение.
  3. В противном случае создайте новый RealConnection. Отказ Инициализируйте его, что будет включать в себя открытие какого-либо сетевого подключения (например, TCP / IP) или дескриптор файлов (для чего-то вроде доступа), пройдите через протокол базы данных для встряхивания рук (варьируется с типом базы данных) и авторизации соединения. Это тогда становится RealConnection для IDbConnection.

Операции выполняются на IDbConnection превращаются в операции RealConnection делает на своем сетевом соединении (или что-то еще). Результаты превращаются в объекты, реализующие IDataReader И так далее, чтобы дать последовательный интерфейс для вашего программирования.

Если IDataReader был создан с CommandBehavior.CloseConnection, Затем, что DataReader получает «владение» RealConnection.

Когда вы называете Close() Тогда происходит одно из следующих:

  1. Если объединение, и если пул не заполнен, то объект помещен в очередь для использования с более поздние операциями.
  2. В противном случае RealConnection Будет проводить любые определенные протоколы процедуры для окончания соединения (сигнализация к базе данных, что соединение будет выключено) и закрывает сетевое соединение и т. Д. Объект может затем выпадать вне охвата и стать доступным для сборки мусора.

Исключение было бы, если CommandBehavior.CloseConnection случай произошел, в этом случае это Close() или Dispose() называется на IDataReader Это вызывает это.

Если вы звоните Dispose() Тогда то же самое происходит в соответствии с Close(). Отказ Разница в том, что Dispose() считается «очисткой» и может работать с using, пока Close() может быть использован в середине жизни, а затем позже Open().

Из-за использования RealConnection Объект и тот факт, что они объединяются, открытия и закрытия соединений изменений от того, чтобы быть чем-то относительно тяжелым до относительно света. Следовательно, вместо того, чтобы в течение длительного времени важно держать соединения, чтобы избежать накладных расходов их открытия, становится важно, чтобы они были открытыми как можно более короткие, так как RealConnection Справляются с накладными расходами для вас, а темнее вы их используете, тем более эффективно объединенные соединения будут общаться между использованием.

Обратите внимание, что это нормально Dispose() ан. IDbConnection что вы уже звонили Close() на (это правило, что всегда должно быть в безопасности, чтобы позвонить Dispose(), Каким бы ни было государство, даже если он уже звонил). Следовательно, если вы были вручно звонить Close() все равно было бы хорошо иметь связь в using Блок, чтобы поймать случаи, когда исключения случаются до вызова Close(). Отказ Единственное исключение - это то, где вы действительно хотите, чтобы соединение осталось открытым; сказать, что вы возвращали IDataReader созданный с CommandBehavior.CloseConnection, в этом случае вы не распорядите IDbConnection, но делать Утилизируйте читатель.

Если вы не сможете распоряжаться соединением, то RealConnection не будет возвращено в пул для повторного использования или пройти через его процедуру отключения. Либо пул достигнет своего пределов, или количество базовых соединений увеличится до точки повреждения производительности и более разблокировки. В конце концов финализатор на RealConnection Может быть вызван и привести к этому фиксированию, но завершение только снижает ущерб и не может быть зависит от. (То IDbConnection не нужен финализатор, так как это RealConnection который содержит неуправляемый ресурс и / или должен сделать выключение).

Также разумно предположить, что существует какое-то другое требование для утилизации уникального для реализации IDbConnection Помимо этого, и он все еще должен быть утилизирован даже если анализ вышеуказанного приводит вас полагать, что это не нужно (исключение, когда CommandBehavior.CloseConnection проходит все нагрузки на удаление к IDataReader, Но тогда это так же важно для утилизации этого читателя).

Другие советы

Хороший вопрос.

Из моих (несколько ограниченных знаний) «недостаточности», работающего SQL-соединения, вовлечены многие шаги, такие как:

Шаги под капотом

  1. Физическая розетка / труба открыта (с использованием приведенных драйверов, например ODBC)
  2. Рукопожатие с SQL Server
  3. Строка подключения / учетные данные договорились
  4. Транзакция Scoping.

Не говоря уже о пуле соединения, я полагаю, что есть какой-то алосмент (если соединительная строка соответствует одному для уже существующего пула, соединение добавляется в пул, в противном случае создается новый)

Idiposable.

Что касается подключений к SQL, мы реализуем iDisposable так, чтобы при вызове отрыва (либо через используемую директиву или откровенность), он помещает соединение обратно в пул соединения. Это в противоположном контрасте с просто простым старым SQLConnection.close () - как все это делает, это временно закрывает, но оставляет за собой соединение для последующего использования.

Из моего понимания .Close () закрывает соединение с базой данных, тогда как .dispose () вызовы .Close () и тогда освобождает неуправляемые ресурсы.

Эти точки в виду, по крайней мере, это хорошая практика для реализации IDSPosable.

Добавление к ответам выше ... Ключ заключается в том, что при «открытии соединения» могут быть выделены ресурсы, которые займут больше, чем стандартная сборка мусора для восстановления, а именно открытой розетки / трубы / IPC onekind. Метод Dispose () очищает их.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top