Jak źle jest nie usuwać () SqlConnections?

14

Osobiście włamuję się do uli, jeśli nie umieszczam obiektów ADO, które implementują IDisposable przy użyciu instrukcji. Ale w ramach mojej obecnej umowy stwierdziłem, że ich domowy kod dostawcy danych „dostawca danych” nie 1) implementuje IDisposable i 2) wywołuje Dispose () na czymkolwiek, z czego korzysta, w dowolnym momencie, kiedykolwiek. Użytkownicy bardzo narzekają na problemy z wydajnością w aplikacjach Winforms, które intensywnie używają tego frameworka do dostępu do danych, i chociaż istnieje wiele innych problemów w kodzie, które mogą pogarszać wydajność, ten po prostu krzyczy na mnie i jest bardziej nisko wiszące owoce niż pozostałe.

Więc poza powiedzeniem czegoś takiego: „Pozbywaj się z jakiegoś powodu, użyj tego”, co mogę powiedzieć tym ludziom, aby przekonali ich, że to naprawdę, naprawdę źle?

AJ Johnson
źródło
5
Heh .. zgaduję, że w pewnym momencie przekonanie nie będzie konieczne :)
dr Hannibal Lecter

Odpowiedzi:

6

Powiedziałbym, że najlepszą rzeczą, jaką możesz zrobić, to wskazać im Wzorce i praktyki Microsoft dotyczące tego Dispose() tematu . Pozwól im zobaczyć pełne konsekwencje niestosowania tego narzędzia, które jest tuż przed nimi.

Jesse C. Slicer
źródło
1
Chciałbym tylko znaleźć wersję, która nie krzyczałaby „to wycofana zawartość” na górze.
AJ Johnson,
Wiesz, moje oczy po prostu się nad tym błyszczały. Ale teraz, czytając go uważnie, zastanawiam się, jakie technologie „ludzie nadal mogą” wykorzystywać, które zostały wycofane z tej strony. Może CAS?
Jesse C. Slicer,
Po dokładniejszym przeanalizowaniu większość z nich nadal wydaje mi się istotna. Nie jestem pewien, dlaczego jest oznaczony jako wycofany.
AJ Johnson,
10

Jeśli nie wywołasz metody Dispose na połączeniu SQL, po zakończeniu korzystania z niego połączenie NIE zostanie zwrócone z powrotem do puli połączeń.

Jeśli masz problemy z wydajnością, domyślam się, że maksymalna liczba połączeń jest otwarta w bazie danych. DBA może to łatwo potwierdzić.

Najlepsza praktyka firmy Microsoft wymaga, abyś umieścił kod połączenia w instrukcji Using, upewniając się, że połączenie jest usuwane i że połączenie jest zwracane z powrotem do puli.

Walter
źródło
Wywołanie Closejest wystarczające, aby zwolnić pulę połączeń. Pytanie nie mówi, że Closenie jest jawnie użyte.
user2864740,
9

Pula połączeń z bazą danych ma ograniczony rozmiar, a jeśli się zapełni, nowe połączenia będą czekać na zwolnienie starych połączeń. Jeśli nie pozbędziesz się ich, gdy tylko z nimi skończysz, zostaną one ostatecznie zwolnione po uruchomieniu finalizatora, ale jest to nieokreślona ilość czasu w przyszłości ... Więc w najlepszym razie zobacz duże opóźnienia przy otwieraniu nowych połączeń.

W najgorszym przypadku mogli wyłączyć pulę połączeń. Być może odkryli, że po pewnym czasie ich aplikacja zwróciła błędy „przekroczenia limitu czasu oczekiwania na połączenie” i wyłączenie puli połączeń „rozwiązało” ten problem. Jest to jednak znacznie gorsze, ponieważ oznacza to, że za każdym razem tworzysz zupełnie nowe połączenie - co zaskakująco wymaga dużych zasobów. Jeśli masz setki połączeń z otwartą bazą danych, nic dziwnego, że widzisz problemy z wydajnością.

Prawidłowym sposobem rozwiązania wszystkich tych problemów jest usunięcie połączenia natychmiast po jego zakończeniu. Najlepiej jest pozostawić połączenie otwarte tak długo, jak to konieczne, i nie dłużej.

Dean Harding
źródło
1
Nawet trochę gorzej. Jeśli pula zostanie wystarczająco zabezpieczona, wiele prób połączenia ostatecznie nie powiedzie się, w tym próby połączenia za pomocą narzędzi do zarządzania, i możesz skutecznie zablokować naszą bazę danych.
Joel Coehoorn
3

W każdym poważnym zastosowaniu powiedziałbym, że jest całkiem zły. Pozostawienie tych obiektów nie tylko unosi się wokół zabójstwa, ale jest po prostu nieprofesjonalne. Dobrą wiadomością jest to, że Microsoft implementuje Finalize w hierarchii obiektów.

~Object()
{
    this.Dispose(false);    
}

public void Dispose()
{
    this.Dispose(true);
    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
    // ...
}

Weźmy System.Data.SqlClient.SqlConnectionna przykład:

System.ComponentModel.Component <- Implementuje wzorzec finalizacji usuwania.
    |
System.Data.Common.DbConnection
    |
System.Data.SqlClient.SqlConnection

Przedmioty zostaną ostatecznie usunięte, ale niedeterministyczna natura powoduje spustoszenie w działaniu.

ChaosPandion
źródło
0

Po pierwsze, nie przerywasz połączenia. Więc albo musi to być: a) automatycznie upuszczone, albo b) przejść cyklicznie i zaktualizowane, nawet jeśli klient nie ma z tego powodu żadnego pożytku.

Zakładam, że b) ze względu na opisywane działanie. Jednak nie jest to prawdopodobnie jedyny powód.

MUSISZ zamykać połączenia, najlepiej po stronie klienta, ale musisz także zaimplementować moduł fail-safe po stronie serwera. W przeciwnym razie masz dodatkowe bzdury na tym, że Twój serwer bazy danych musi przetwarzać, dopóki nie zostanie wydany w chwili, gdy Bóg wie.


źródło