30

MVC 3 + EF 4.1Jaki jest najlepszy sposób tworzenia i usuwania DbContext w MVC?

mam wybór między dwoma podejściami do czynienia z DbContext:

  1. instancji w Application_BeginRequest, umieścić go w HttpContext.Current.Items i rozporządzania w Application_EndRequest.
  2. Tworzenie jednorazowy UnitOfWork (kindof wrapper dla DbContext) i rozpoczęcie każdego działania kontrolera z using(var unitOfWork = new UnitOfWork()) { ... }

Podziel się doświadczeniem proszę: Które jeden wolisz? jakie są plusy i minusy dla każdego podejścia?

+0

Zastosowanie metody blokowej ma pewne wady. Powoduje wiele podróży w obie strony do bazy danych i nadużycia transakcji w ramach Entity. odnieść się do http://ayende.com/blog/4775/new-profiler-feature-avoid-writes-from-multiple-sessions-in-tame-reame-request – marvelTracker

+0

Dlaczego powoduje więcej wizyt w obie strony?Jedno żądanie http powinno w większości przypadków uruchomić jedną akcję, więc jeśli zawiniesz cały kod akcji do tego bloku, nie będzie więcej żądań bazy danych w porównaniu z pierwszym podejściem. Inną rzeczą przy podejściu "na działanie" jest to, że powinieneś zawsze być świadomym zakresu, w jakim baza danych może zostać przywołana i odpowiednio ustawić blok. Na przykład, jeśli twój model zawiera pewną kolekcję, która ma być leniwą ładowaną w czasie Wyświetlanie widoku, powracanie widoku View (Model) powinno znajdować się wewnątrz bloku. – YMC

+0

Jeśli używasz DbContext w wrapperu warstwy kontrolera, UnitOfWork tworzy silne uzależnienie od warstwy interfejsu i podejścia do bazy danych. Następnie potrzebujesz warstwy serwisowej i warstwy repozytorium. Następnie, jeśli twoje repozytoria mają oddzielne UnitOfWork z użyciem bloków, które będą stanowić problem. ponieważ każde repozytorium tworzy transakcje i niepotrzebne obie strony w bazie danych. Zobacz powyższy link, aby uzyskać więcej szczegółów. jeśli masz pewność co do jednego zgłoszenia serwisowego na żądanie, możesz użyć unitofwork wewnątrz metody serwisowej. Jednak nie jest to gwarancja. – marvelTracker

Odpowiedz

18

Proponuję użyć ramy iniekcji zależność. Możesz zarejestrować swoją DbContext jak na zamówienie

container.RegisterType<MyDbContext>().InstancePerHttpRequest(); 

i wstrzyknąć go jako parametr konstruktora do sterownika.

public class MyController : Controller 
{ 
    public MyController(MyDbContext myDbContext) 
    { 
     _myDbContext = myDbContext; 
    } 
} 

Jeśli zarejestrowanym typ implementuje IDisposable następnie ramy DI będzie go wyrzucać, gdy żądanie kończy.

Pierwsze podejście: O wiele bardziej przejrzyste jest używanie ramek ID niż ręczne ich wdrażanie. Dalej wszystkie twoje prośby mogą nie wymagać twojej pracy.

Drugie podejście: kontroler nie powinien wiedzieć, jak skonstruować UU (DbContext). Celem nie jest zmniejszenie sprzężenia między komponentami.

+0

Dobrze, lepiej używać kontenera IoC niż obsługi BeginRequset i EndRequest, ale nadal wydaje mi się to dość zbliżone do numeru 1, dlatego nawet nie wyodrębniłem go jako osobnego podejścia. Co ważniejsze dla mnie jest porównanie 2 sposobów dostępu i kontroli cyklu życia DbContext (= Unit Of Work): pierwszy sposób sugeruje, że jest za to odpowiedzialna infrastruktura ASP.NET/IoC, druga dotyczy każdej akcji kontrolera, opłata. – YMC

+0

@ YMC Edytowana odpowiedź. Twoje drugie podejście wprowadzi sprzężenie między twoim kontrolerem a implementacją UoW. Proponuję ci tego unikać. – Eranga

+3

Przedstaw warstwę usług i wstrzyknij usługi kontrolerowi. Usługa może mieć wiele repozytoriów i repozytoriów zależnych od zawijania UnitOfWork z EFDbContext. Następnie użyj DI, aby wstrzyknąć te uzależnienia. Następnie możesz skorzystać z opcji Rozdzielanie wątpliwości. – marvelTracker

-1
+2

OP nie powiedział nic o umieszczeniu DbContext w statycznym polu ... chce umieścić to w HttpContext.Current.Items, co jest całkowicie bezpieczne, o ile widzę –

+0

Nie powiedziałem, że umieszczam DbContext w global.asax . Powiedziałem, że umieszczam kod, który tworzy instancje i udostępnia DbContext. DbContext znajduje się w HttpContext.Current.Items. Jest bezpieczny dla wątków. – YMC

2

Obecnie korzystamy z repozytoriów wstrzykniętych z UoW (jednostka pracy) utworzonych za pomocą lokalizatora usług z fabryki repozytoriów. Jedność kontroluje życie w ten sposób, zabierając pracę z dala od ciebie.

Twój szczególności realizacja będzie się różnić w zależności, czy przy użyciu POCO'S, Entity Objects, etc ..

Ostatecznie chcesz UOW jeśli zamierzasz pracować z więcej niż jednym ObjectSet w kontrolerze, aby zapewnić tylko przy użyciu jednego kontekstu . To sprawi, że twoje transakcje zostaną sprawdzone itd.

Jeśli zamierzasz używać wielu tekstów kontekstowych (np. Wiele EDMX), będziesz chciał spojrzeć na użycie UoW z MSDTC ... ale to prawdopodobnie więcej niż chciałeś wiedzieć . Na koniec ważne jest, abyś zademonstrował to, czego potrzebujesz do działania kontrolera (tj. Do jednego wystąpienia kontekstu). Nie sądzę, abym poszedł z Begin_Request, może nawet nie potrzebujesz kontekstu dla każdego żądania.

Powiązane problemy