Chodźmy kontrowersyjny!
Nie zgadzam się z ogólnym MVC + EF konsensusu, że utrzymanie kontekst żyje przez cały wniosek jest dobrą rzeczą dla wielu powodów:
wzrost Niska wydajność Czy wiesz jak drogie stworzenie nowy kontekst bazy danych to? Dobrze...„DataContext jest lekki i nie jest drogie, aby utworzyć” to z MSDN
Get MKOl źle i będzie się wydawać w porządku .. aż pójdziesz na żywo Jeśli skonfigurowaniu kontenera IoC do dysponowania Twój kontekst dla ciebie, a ty źle, naprawdę źle. Mam teraz dwa razy widziałem ogromne przecieki pamięci utworzone z kontenera IoC nie zawsze poprawnie pozbywając się kontekstu. Nie zauważysz, że źle ustawiłeś, dopóki twoje serwery nie zaczną się rozpadać podczas normalnego poziomu jednoczesnych użytkowników. Nie stanie się to w fazie rozwoju, więc wykonaj kilka testów obciążenia!
Przypadkowe lazy loading Państwo zwrócić IQueryable swoich ostatnich artykułów, dzięki czemu można je wymienić na swojej stronie głównej. Pewnego dnia ktoś inny zostanie poproszony o wyświetlenie liczby komentarzy obok odpowiedniego artykułu. Więc dodać prosty kawałek kodu do widoku pokazać liczbę Komentarz Lubie tak ...
@foreach(var article in Model.Articles) {
<div>
<b>@article.Title</b> <span>@article.Comments.Count() comments</span>
</div>
}
Wygląda w porządku, działa bez zarzutu. Ale w rzeczywistości nie uwzględniłeś komentarzy w swoich zwróconymi danymi, więc teraz zrobi to nowe wywołanie bazy danych dla każdego artykułu w pętli. WYBIERZ N + 1 problem. 10 artykułów = 11 wywołań bazy danych. Okay, więc kod jest błędny, ale łatwo popełnić błąd, aby tak się stało.
Możesz temu zapobiec, zamykając kontekst w swojej warstwie danych. Ale czy kod nie będzie łamał się z wyjątkiem NullReferenceException na article.Comments.Count()? Tak, spowoduje to zmianę warstwy, aby uzyskać dane potrzebne dla warstwy widoku. Tak powinno być.
Zapach kodu Jest coś nie tak z trafieniem w bazę danych z widoku. Wiesz, że IQueryable tak naprawdę nie trafiło w bazę danych, więc zapomnij o tym obiekcie. Upewnij się, że twoja baza danych została trafiona, zanim opuści twoją warstwę danych.
Więc odpowiedź
Kod powinien być (moim zdaniem) jak to
dataLayer:
public List<Article> GetArticles()
{
List<Article> model;
using (var context = new MyEntities())
{
//for an example I've assumed your "MyTable" is a table of news articles
model = (from mt in context.Articles
select mt).ToList();
//data in a List<T> so the database has been hit now and data is final
}
return model;
}
Kontroler:
public ActionResult Index()
{
var model = new HomeViewModel(); //class with the bits needed for you view
model.Articles = _dataservice.GetArticles(); //irrelevant how _dataService was intialised
return View(model);
}
Po dokonaniu to i rozumiem to może wtedy yo możesz zacząć eksperymentować z posiadaniem kontekstu uchwytu kontenera IoC, ale zdecydowanie nie wcześniej. Kieruj moim ostrzeżeniem - widziałem dwie duże awarie :)
Ale szczerze, rób to, co lubisz, programowanie jest zabawne i powinno być kwestią preferencji. Po prostu ci mówię. Ale cokolwiek robisz, nie zaczynaj używać kontekstu IoC na kontroler lub żądanie, tylko dlatego, że "robią to wszystkie fajne dzieciaki". Zrób to, ponieważ naprawdę dbasz o jego zalety i rozumiesz, jak to działa poprawnie.
'model = context.MyTable.ToList()' - 'ToList()' wykona zapytanie. W twoim przypadku IQueryable nie działałby poza zakresem kontekstu. – Andrei