2010-04-21 15 views
5

Załączam moje wywołania linq do sql w klasie repozytorium, która jest tworzona w konstruktorze mojego przeciążonego kontrolera. Konstruktor mojej klasy repozytorium tworzy kontekst danych, tak aby na czas ładowania strony był używany tylko jeden kontekst danych.Dlaczego moje połączenia nie są zamknięte, nawet jeśli jawnie pozbywam się DataContext?

W moim destruktorze klasy repozytoriów wyraźnie nazywam zbycie DataContext, chociaż nie uważam, że jest to konieczne.

Korzystając z monitora wydajności, jeśli obserwuję liczbę połączeń użytkownika i wielokrotnie ładuję stronę, liczba zwiększa się raz na wczytywanie strony. Połączenia nie są zamykane lub ponownie używane (przez około 20 minut).

Próbowałem wstawiania Pooling = false w mojej konfiguracji, aby zobaczyć, czy to miało jakiś wpływ, ale tak się nie stało. W każdym razie przy łączeniu nie spodziewałbym się nowego połączenia dla każdego obciążenia, oczekiwałbym, że ponownie użyje połączeń.

Próbowałem umieścić punkt przerwania w destruktorze, aby upewnić się, że utylizacja jest trafiona i na pewno jest. Więc co się dzieje?

Niektóre kodu do zilustrowania tego, co powiedziałem powyżej:

kontroler:

public class MyController : Controller 
{ 
    protected MyRepository rep; 

    public MyController() 
    { 
     rep = new MyRepository(); 
    } 
} 

Repozytorium:

public class MyRepository 
{ 
    protected MyDataContext dc; 

    public MyRepository() 
    { 
     dc = getDC(); 
    } 

    ~MyRepository() 
    { 
     if (dc != null) 
     { 
      //if (dc.Connection.State != System.Data.ConnectionState.Closed) 
      //{ 
      // dc.Connection.Close(); 
      //} 
      dc.Dispose(); 
     } 
    } 

    // etc 
} 

Uwaga: dodam kilka wskazówek i informacji kontekście do DC do celów audytu. Jest to w zasadzie dlaczego chcę jednego połączenia za ładowania strony

Aktualizacja: Po wdrożone IDisposable na moim repozytorium i na mojej klasie kontrolera nie mogłem znaleźć sposób, aby specjalnie wywołujemy metodę Dispose na moim kontrolera jako kontroler jest tworzony i niszczony za kulisami przez MvcHandler. Jednak odkryłem, że i tak moje połączenia są zamknięte. I nie było wygodne, wiedząc, że to działa, ale nie wiedząc dlaczego tak zrobiłem kilka kopanie i znaleźć cytat MSDN że mnie ucieszyło:

Kiedy wykonanie jest kompletny, MvcHandler sprawdzi, czy sterownik implementuje IDisposable interfejs, a jeśli tak, wywoła funkcję Dispose na kontrolerze, aby wyczyścić niezarządzane zasoby.

Finał Aktualizacja: Po miesiącu lub tak z pracy to ja teraz wyjąć cały ten kod i zszedł MS zaleca trasę owijania „używając” oświadczenie wokół kodu w moich metodach repozytorium publicznych i przekazywanie tego DC do prywatnych metod. Wydaje się to trochę marnotrawstwem i powtarzalnością, a także powoduje, że kilka kolejnych połączeń jest otwieranych i zamykanych. Ale otrzymywałem linq do sql caching, które mogłem rozwiązać tylko przez zresetowanie DC.

Odpowiedz

4

Prawidłowy wzór (krótka, ale wystarczająca wersja) to:

public class MyRepository : IDisposable 
{ 
    ... // everything except the dtor 

    public void Dispose() 
    { 
     if (dc != null) 
     { 
      dc.Dispose(); 
     } 
    } 
} 

public class MyController : Controller, IDisposable 
{ 
    protected MyRepository rep; 

    public MyController() 
    { 
     rep = new MyRepository(); 
    } 

    public void Dispose() 
    { 
     if (rep!= null) 
     { 
      rep.Dispose(); 
     } 
    } 
} 

I teraz można (należy) używać MyController z użyciem klauzuli:

using (var ctl = new MyController()) 
{ 
    // use ctl 
} 

EDIT:
Właśnie zauważyłem, że kaskady do MyController, kod dodaje. Pokazuje to, jak rozprzestrzenia się pośrednia własność niezarządzanego zasobu.

Edit 2:
to również prawidłowe (jak byłoby to try/finally):

var ctl = GetController(); 
using (ctl) 
{ 
    // use ctl 
} 

Jeśli nie można zachować to lokalny do 1 sposobu, po prostu jak najlepiej, aby zadzwonić CTL .Dispose() w przypadku zamknięcia lub podobnego.

+0

ahh, dzięki. Właśnie zastanawiałem się, czy mój kod wymagał dodania również (odnosząc się do edycji) –

+0

Nie jestem pewien co do ostatniego fragmentu. MVC generuje mój kontroler, więc jak mam się upewnić, że jest prawidłowo utylizowany? –

+0

@Chris, bądź ostrożny przy dziedziczeniu, zauważam, że zrobiłeś pola chronione. Nie zrobiłbym tego. –

2

Destruktory są wywoływane tylko przez GC. Twój MyRepository powinien wdrożyć wzór Dispose i zutylizować tam DC.

Zobacz to pytanie, aby uzyskać więcej informacji. In C# what is the difference between a destructor and a Finalize method in a class?

MyRepository powinny zaimplementować IDisposable, wszelkie przedmioty jednorazowego użytku powinny zostać usunięte tam, jeśli trzymasz je otwarte przez cały czas istnienia obiektu.

Większość czasu, gdy jesteś przy użyciu jednorazowej obiektu należy owinąć go w wykorzystaniem bloku

tj

using(var dc = getDC()) 
{ 
    //do stuff with the dc 
}//the dc will be Disposed here 

Edit: Link do przewodnika językowego dla C# destruktorów http://msdn.microsoft.com/en-us/library/66x5fx1b(v=VS.100).aspx

+0

I __not__ zaimplementować destruktor. W tej klasie nie ma sensu. –

+0

ahh, czy mówisz, że Dispose nie powinno być wywoływane w destruktorze? –

+0

Uzgodnione destruktory rzadko mogą być używane w aplikacji C#. –

0

Zgadzam się z tym, że jednorazowe części były niepoprawne, a powyższe sugestie autorstwa Henk Holterman i Darryl Braaten są bardzo dobre, nie sądzę, że odpowiadają na podstawowe pytania.

Odpowiedź na pytanie brzmi, że wywołanie utylizacji na MyRepository (przy założeniu, że jest to DataContext) nie powoduje zamknięcia połączenia. Po prostu zwraca połączenie z pulą do następnego użycia.

This SO Post wyjaśnia, kiedy należy się martwić o połączeniach zamykających ...

+0

Pierwotne pytanie już dotyczy pulowania ("Połączenia nie są zamykane lub ponownie używane ...") –

+0

Czy możesz to zmienić? Nie rozumiem? – Nix

+0

Wygląda na to, że połączenie nie jest zwracane do puli. Niezależnie od tego, czy pule są włączane czy wyłączane, nowe połączenia są zawsze tworzone i nie są ponownie używane. –

Powiązane problemy