Andiamo controverso!
Non sono d'accordo con il generale MVC + EF consenso che mantenere in vita un contesto in tutta l'intera richiesta è una buona cosa per una serie di motivi:
scarso aumento delle prestazioni Sai come costosa la creazione di un il nuovo contesto del database è? Bene..."Un DataContext è leggero e non è costoso per creare" che è da MSDN
Prendi il CIO sbagliato e sembrerà bene .. fino a quando si va in diretta Se si imposta il contenitore CIO di disporre di il tuo contesto per te e te lo sbagli, davvero ti sbagli davvero. Io ho due volte ora ho visto enormi perdite di memoria create da un contenitore IoC che non sempre smaltiscono correttamente un contesto. Non ti accorgerai di averlo impostato erroneamente fino a quando i tuoi server non si saranno sbriciolati durante i normali livelli di utenti concorrenti. Non accadrà nello sviluppo, quindi esegui alcuni test di carico!
Caricamento pigro accidentale Si restituisce un IQueryable dei tuoi articoli più recenti in modo che sia possibile elencarli nella tua home page. Un giorno a qualcun altro viene chiesto di mostrare il numero di commenti accanto al rispettivo articolo. In modo da aggiungere un po 'di semplice codice alla vista per mostrare il numero di commenti in questo modo ...
@foreach(var article in Model.Articles) {
<div>
<b>@article.Title</b> <span>@article.Comments.Count() comments</span>
</div>
}
guarda bene, funziona bene. Ma in realtà non hai incluso i commenti nei tuoi dati restituiti, quindi ora questo farà una nuova chiamata al database per ogni articolo nel ciclo. SELEZIONA N + 1 problema. 10 articoli = 11 chiamate al database. Ok, quindi il codice è sbagliato ma è un errore facile farlo in modo che accada.
È possibile evitare ciò chiudendo il contesto nel proprio livello dati. Ma il codice non si romperà con una NullReferenceException sull'articolo.Comments.Count()? Sì, così sarà costretto a modificare il livello Data per ottenere i dati necessari per il livello Visualizza. Questo è come dovrebbe essere.
Codice odore C'è solo qualcosa di sbagliato nel colpire il database dalla Vista. Sai che un IQueryable in realtà non ha colpito il database ancora giusto, quindi dimentica quell'oggetto. Assicurati che il tuo database sia colpito prima che lasci il tuo livello dati.
Quindi la risposta
Il codice dovrebbe essere (a mio parere) come questo
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;
}
Controller:
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);
}
volta che avete fatto questo e capisci questo allora forse yo Puoi iniziare a sperimentare con il contesto di gestire un contenitore IoC, ma sicuramente non prima. Testa il mio avvertimento - Ho visto due errori su larga scala :)
Ma sinceramente fai quello che ti piace, la programmazione è divertente e dovrebbe essere una questione di preferenza. Ti sto solo raccontando il mio. Ma qualunque cosa tu faccia, non iniziare a utilizzare il contesto IoC per controller o per richiesta solo perché "tutti i ragazzi fantastici lo stanno facendo". Fallo perché tieni veramente a cuore i suoi benefici e capisci come è fatto correttamente.
'model = context.MyTable.ToList()' - 'ToList()' eseguirà la query. Nel tuo caso IQueryable infatti non funzionerebbe al di fuori dell'ambito del contesto. – Andrei