2009-05-22 9 views
5

Czy dobrą praktyką jest posiadanie jednego współdzielonego obiektu SqlConnection w aplikacji .NET do używania we wszystkich połączeniach z bazą danych lub czy powinien on mieć osobny przy każdym dostępie do bazy danych?Shared SqlConnection

Obecnie mam jedną wspólną i wydaje się, że pojawiają się nagle problemy. Wygląda na to, że nie mogę użyć współdzielonego, gdy potrzebuję użyć trybu uwierzytelniania SQL zamiast trybu uwierzytelniania systemu Windows. Po raz pierwszy próbowałem użyć uwierzytelniania SQL i otrzymałem ten błąd, gdy próbowałem użyć tego samego połączenia po raz drugi:

Istnieje już otwarty obiekt DataReader powiązany z tym rozkazem, który musi zostać zamknięty jako pierwszy.

Odpowiedz

4

Naprawdę powinieneś mieć oddzielny. Ponowne używanie połączeń jest obsługiwane za pomocą connection pooling. Drugi problem, jak powiedzieli inni, może prawdopodobnie zostać rozwiązany poprzez włączenie MARS.

0

Jeśli używasz programu SQL Server 2000, this może odpowiedzieć na twoje pytanie.

Wygrywająca odpowiedź brzmi: "Jest to spowodowane zmianą domyślnego ustawienia MAR. Był on domyślnie włączony i domyślnie zmieniliśmy go na RC1. Więc po prostu zmień ciąg połączenia na dodaj go ponownie (dodaj MultipleActiveResultSets = True do ciągu połączenia). "

1

Wiele z tego może być dup from here; w skrócie, utrzymuj połączenia krótkotrwałe i lokalne w większości przypadków. Re czytnik danych; może umożliwić MARS?

1

Podczas gdy dla pojedynczego wątku może lepiej korzystać z pojedynczego obiektu SqlConnection, stawia wymagania dla cennego zasobu, który jest serwerem bazy danych, zawieszając się na połączeniu, a tym samym zasobów serwera bazy danych, dłużej niż to konieczne.

Lepiej utworzyć instancję SqlConnection na tak krótki czas, jak to możliwe. Pule połączeń zmniejszają większość kosztów związanych z konfigurowaniem połączenia i zapewniają najbardziej wydajne wykorzystanie zasobów bazy danych.

3

Ten błąd nie ma absolutnie nic wspólnego z uwierzytelnianiem. Ponownie używasz połączenia od środka, zanim zamknąłeś swój SqlDataReader zwrócony z ExecuteReader(). To jest zabronione. Musisz sprawdzić swój kod i wyeliminować swój problem. Istnieją alternatywy do używania MARS (multiple active record sets), ale zdecydowanie odradzam to.

Korzystanie z wielu połączeń w aplikacji będzie prawdopodobnie jeszcze gorsze, ponieważ najwyraźniej nie wiesz, jakie połączenia są w użyciu i kiedy, więc kiedy będziesz używać oddzielnych połączeń, napotkasz problemy z konsekwencją transakcji.

+0

Jeśli mówisz "nie korzystaj z MARS" - czy masz jakieś konkretne powody? Z ciekawości ... –

+0

http://blogs.msdn.com/sqlnativeclient/archive/2006/09/27/774290.aspx omawia niektóre z negatywów używania MARS – RichardOD

+2

Model izolacji transakcji MARS jest niekompletny, jak w nie do końca zdefiniowane teoretycznie. W rezultacie serwer może zostać "zdezorientowany", jak podaje link zamieszczony przez Richarda. Zwykle oznacza to, że liczba możliwych interakcji jest zbyt duża i nie wszystkie ścieżki kodu na serwerze są testowane i sprawdzane. –

2

Twój problem polega na tym, że próbujesz użyć połączenia, które jest aktualnie używane przez SqlDataReader. Nie możesz tego zrobić. Kiedy używasz SqlDataReader, musisz zamknąć go przed ponownym użyciem połączenia, które jest zużywane. Proponuję utworzyć inne połączenie przy każdym dostępie do bazy danych (w dowolnym momencie, nie tylko z SqlDataReaders). Jeśli włączona jest opcja łączenia, to sama struktura (lub serwer SqlServer?) Ponownie użyje połączeń, jeśli to możliwe.

Jeśli potrzebujesz dostępu do bazy danych sekwencyjnie, powiedzmy, że wybierasz, a następnie wybierz, a następnie aktualizację, możesz ponownie użyć połączenia (to znaczy tej samej instancji SqlConnection), ale jeśli potrzebujesz dostępu DB podczas odczytu z SqlDataReader, potrzebujesz 2 różnych połączeń.

Oczywiście trzeba mieć na uwadze kwestie współbieżności.Jeśli korzystasz z transakcji, niektóre rekordy mogą być blokowane podczas pewnych operacji, a gdy używasz SqlDataReader równolegle z innymi kwerendami, powinieneś ustawić poziom izolacji na poziomie, który nie zepsuje się z pozostałymi zapytaniami.

Powiązane problemy