2010-01-18 11 views
6

Mam metodę ("GetDataReader", nazwijmy to), która zwraca SqlDataReader. Jest wewnątrz klasy Singleton DataFactory, która utrzymuje stałe połączenie z bazą danych.Jak mogę "odłączyć" SqlDataReader od jego obiektu SqlConnection?

Problem z tym, że po zwrocie, DataReader jest nadal "podłączony" do obiektu Connection w moim DataFactory. Tak, muszę się upewnić, że kod, który wywołuje GetDataReader następnie wywołuje Close() na DataReader że wraca, Inaczej, „zamki” Połączenie z tego:

Jest już otwarty DataReader skojarzony z tym Polecenie, które należy najpierw zamknąć.

Jak mogę "odłączyć" DataReader przed odesłaniem go z GetDataReader? Albo to, sklonuj i odeślij klon? Nie chcę, aby kod wywołujący zawsze wyraźnie go zamykać.

Tu musi być najlepsza praktyka.

Aktualizacja:

Dzięki wszystkim za wkład. Najważniejsze jest to, że muszę stracić nawyk używania DataReaderów i przejść na DataTables. Są znacznie łatwiejsze w zarządzaniu.

Dziękuję również za uwagę na temat łączenia połączeń. Wiedziałem o tym, ale po prostu nie wstawiłem dwóch i dwóch razem i nie zdałem sobie sprawy, że ponownie wynajduję koło.

+0

ja * * mam przestać używać DataReaders ... – Deane

Odpowiedz

6

dataReader musi pozostawać w kontakcie z db aż już nie są potrzebne - to charakter użyciu DataReader więc można nie „Disconnect” nich jako takie. Po zakończeniu pracy z czytnikiem danych zamknij go (.Close()), ale nie możesz go już użyć.

Od wersji .NET 2.0, jeśli korzystasz z SQL 2005 lub nowszego, możesz skorzystać z MARS (wiele aktywnych zestawów wyników) zgodnie z wyjaśnieniami here. Pozwala to na użycie jednego połączenia dla wielu czytników danych i wymaga zmiany ciągu połączenia. Jednak SqlDataReaders nie są idealne do przekazywania kodu w sposób, w jaki brzmi, jak chcesz.

Alternatywnie (czyli to, co myślę, że trzeba to zrobić), może chcesz użyć odłączonego resultset który gdzie DataSet/DataTables przyjść. Możesz użyć SqlDataAdapter wypełnić DataSet/DataTable ze wszystkich wyników operacji pytanie. Następnie można użyć tego połączenia do dowolnego innego celu lub zamknąć połączenie i nie ma to wpływu na zestaw wyników w pamięci. Możesz przekazać swój zestaw wyników wokół kodu bez potrzeby utrzymywania otwartego połączenia z bazą danych.

+0

Tak, DataTables są lepsze podejście tutaj. Muszę przestać używać DataReaders. Już wcześniej wpadłem na ten problem - mam nadzieję, że tym razem nauczę się mojej lekcji. Dzięki. – Deane

2

Nie utrzymuj połączenia z bazą danych. Istnieje funkcja o nazwie "pooling połączeń". Uzyskanie świeżego połączenia nie jest drogie.

1

Ogólnie rzecz biorąc, najlepszą praktyką byłoby korzystanie z łączenia połączeń zamiast stałego połączenia, aby umożliwić równoczesny dostęp wielu użytkownikom. Jedynym sposobem na zrobienie tego, co chcesz zrobić, byłoby wczytanie DataSet z czytnika i zwrócenie go.

0

Wydaje mi się, że twoje zestawy danych (odłączone dane osadzone) i datareadery (brak danych) mogą być pomieszane. DataReader bez SqlCnnection jest ... ummm ... po prostu Reader, tj. Brak danych ;-)

Myślę, że twój problem jest dalej w górę twój sposób myślenia. Domyślam się, że jesteś staroświeckim programistą, który robił wszystko ręcznie. W "zarządzanym" świecie sieci dotowej wiele rzeczy jest zarządzanych dla ciebie; ADO.NET ma już skuteczny system łączenia danych, nie trzeba utrzymywać własnej puli.

-Oisin

0

Oto przydatny metoda pomocnika wykonać pewne SQL przed połączeniem, i to odłączony od serwera:

public static DbDataReader ExecuteReaderClient(DbConnection connection, DbTransaction transaction, String commandText) 
{ 
    DbCommand command = connection.CreateCommand(); 
    command.CommandText = commandText; 
    if (transaction != null) 
     command.Transaction = transaction; 

    DbDataAdapter adapter = DbProviderFactories.GetFactory(connection).CreateDataAdapter(); 

    adapter.SelectCommand = command; 
    DataSet dataset = new DataSet(); 

    try 
    { 
     adapter.Fill(dataset); 
    } 
    catch (Exception e) 
    { 
     throw new Exception(
        e.Message + "\r\n" + 
        "Command Text" + "\r\n" + 
        commandText, e); 
    } 

    try 
    { 
     return dataset.CreateDataReader(); 
    } 
    finally 
    { 
     dataset.Dispose(); 
    } 
} 
Powiązane problemy