applБудет ли окончательно закрытое не правильно закрытое DBConnection после GC (после длительного времени) - PullRequest
0 голосов
/ 09 января 2019

У меня есть устаревшие коды (формы VB6), которые следуют шаблону плохого дизайна. Он подключается к базе данных в конструкторе и закрывает ее в деструкторе класса (т. Е. Class_Terminate для VB6).

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

Мы сейчас переносим его на .NET и столкнулись с проблемой. Поскольку при переносе ADO в ADO.NET (это жесткое требование) закрытие соединения ADO.NET в методе Finalize вызовет исключение.

(Более подробное объяснение: Исключение: InvalidOperationException: дескриптор не инициализирован. Наблюдайте за объектом соединения, состояние все еще открыто. Из предыдущих вопросов в StackOverflow люди предлагали открывать и закрывать соединение сразу после использования, и не не держать соединение открытым в течение всего срока службы объекта класса.)

Я искал и обнаружил, что в .NET только неуправляемые ресурсы будут освобождены в Finalize. Такие объекты, как DBConnection, не должны закрываться в методе Finalize.

Это довольно неловкая ситуация. На данный момент лучший способ для нас, по-видимому, - не закрывать каждое соединение после использования и повторно открывать его перед использованием (это отнимает много времени). На самом деле мы рассматриваем игнорирование исключения во время метода Close in Finalize.

Я хотел бы спросить,

1) Реализует ли DBConnection в ADO.Net метод Finalize и закрывает ли реальное базовое соединение во время GC? Если это так, то игнорируйте исключение close в Finalize), которое не нанесет нам вреда.

2) Если нет, будут ли окончательно возвращены базовые соединения (возможно, из пула соединений?) Обратно в систему или пул соединений? Скажите, что система или пул соединений будут проверять ненормальные состояния соединения и возвращать ресурсы через некоторое время?

Спасибо.

1 Ответ

0 голосов
/ 13 января 2019

1) Реализует ли DBConnection в ADO.Net метод Finalize и закрывает ли реальное базовое соединение во время GC? Если это так, тогда игнорируйте исключение close в Finalize), которое не нанесет нам вреда.

2) Если нет, будут ли окончательно возвращены базовые соединения (возможно, из пула соединений?) Обратно в систему или пул соединений? Скажите, что система или пул соединений будут проверять ненормальные состояния соединения и возвращать ресурсы через некоторое время?

  1. Сборщик мусора будет собирать только управляемый код. Вот почему у нас есть интерфейс IDisposable.
    Базовое соединение не является управляемым кодом и поэтому не будет закрыто сборщиком мусора.

  2. Пул соединений закроет базовое соединение через x раз, когда оно закрыто и не используется. «Реальное» соединение с базой данных, привязанное к открытому экземпляру IDbConnection, будет недоступно для выдачи или закрытия пула соединений.

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

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

Однако вы можете создать свои собственные классы, чтобы добавить слой между кодом приложения и кодом ADO.Net, и вместо сопоставления ADO непосредственно с ADO.Net сопоставьте его с вашим собственным классом.

Таким образом, в основном у вас будет класс Connection, который реализует интерфейс IDbConnection, и класс Command, который реализует интерфейс IDbCommand.

В вашей реализации IDbCommand вы должны открывать и закрывать фактическое соединение при выполнении командных методов.

Таким образом, у вас есть сравнительно небольшой объем работы по сопоставлению старого кода с новым кодом, и все преимущества использования соединения только тогда, когда оно вам действительно нужно.

...