2013-05-08 9 views
5
Abfrage

ich von hierWie zurückkehren IQueryable <T> zur weiteren

https://github.com/TroyGoode/PagedList

die PagedList.Mvc Bibliothek bin versucht, die dieses Anwendungsbeispiel

var products = MyProductDataSource.FindAllProducts(); //returns IQueryable<Product> representing an unknown number of products. a thousand maybe? 

     var pageNumber = page ?? 1; // if no page was specified in the querystring, default to the first page (1) 
     var onePageOfProducts = products.ToPagedList(pageNumber, 25); // will only contain 25 products max because of the pageSize 

typische implmentations von MyProductDataSource.FindAllProducts hat (); entlang der Linien sind

public IQuerable<T> MyProductDataSource.FindAllProducts() 
{ 
    using (var ctx = new MyCtx()) 
    { 
     return ctx.MyList().Where(....); 
    } 
} 

was natürlich die InvalidOperationException hat() und DbContext ist bereits Nachricht

der Suche nach Best Practices, wie zurückzukehren IQueryable angeordnet, die ohne Probleme hier verwendet werden können?

+0

Dies ist KEINE typische Implementierung. Normalerweise injizieren Sie einen Kontext in eine Repository-Klasse, was bedeutet, dass Sie nicht auf Methodenebene verfügen. –

+0

@WiktorZychla Ich stimme nicht zu. Beide sind nützliche Implementierungen. Wenn es möglich ist, den Kontext lokal auf die Methode zu beschränken, ist dies eine akzeptable Aufgabe. Wenn die Generierung der Abfrage jedoch über den Bereich dieser Methode hinausgeht, die keine Option ist, müssen Sie in solchen Fällen den Umfang des Kontexts anpassen dass es, wo auch immer es ist, die Lebensdauer dieser Abfrage umfasst. Programmierer sollten in der Lage sein zu verstehen, was die Lebensdauer einer gegebenen Abfrage ist, und den Kontext so abgrenzen, dass er auf der gleichen "Ebene" ist, nicht mehr und nicht weniger. – Servy

+0

@Servy: Wahr, aber in den meisten Fällen ist die Lebensdauer Ihres Kontextes "per-http-context". Beachten Sie, dass er die Frage mit asp.net markiert.Was Sie sagen, ist ein Teil einer allgemeinen Theorie, er braucht eine genaue Anleitung für sein spezifisches asp.net-Szenario. –

Antwort

3

Sie müssen „move up“ der Umfang Ihres Datenkontextes:

public IQueryable<T> MyProductDataSource.FindAllProducts(MyCtx context) 
{ 
    return context.MyList().Where(....); 
} 

dann den Kontext am größeren Umfang erstellen:

using (var ctx = new MyCtx()) 
{ 
    var products = MyProductDataSource.FindAllProducts(ctx); 

    var pageNumber = page ?? 1; 
    var onePageOfProducts = products.ToPagedList(pageNumber, 25); 
} 
+0

Eine Alternative wäre, den Kontext in die Datenquelle anstatt in jede einzelne Methode davon zu injizieren. –

+0

@WiktorZychla Der Punkt ist, dass die Lebensdauer des Kontexts erhöht werden muss, um die Lebensdauer der Abfrage zu überschreiten, wie hoch Sie gehen müssen, um dies zu erreichen, kann natürlich basierend auf der Abfrage variieren. Möglicherweise muss es sich im Bereich dieses Objekts befinden oder nicht. – Servy

+0

Ich denke, dass sollte IQueryable sein –

4

Die gute Praxis ist die Lebensdauer zu halten DbContext als per HTTP-Anfrage mit IoC-Container, unterstützen die meisten IoC-Container HttpRequest Lebensdauer.

So können Sie den Geltungsbereich von DbContext nutzen, mit dem Sie IQueryable auf der oberen Ebene verwenden können.

Weitere Informationen, die zwei IoC Container Ich mag: Autofac und ninject.

Wie autofac MVC here

unterstützt in Oder wie NInject unterstützt MVC in here

Wenn Sie auf IoC-Container neu sind, würden Sie vorschlagen, sollten Sie ein das Grundkonzept der dependency injection von Martin Blume und anschauen. Dann fahren Sie mit einem von Ihnen gewählten IoC-Container fort.

Aber Sie müssen sehr vorsichtig sein, wie Sie IQueryable verwenden und welche Schicht Sie aufhören sollten, es zu unterstützen. Wenn nicht, der Teufel hinter, Lazy Loading von Entity-Framework wird die Leistung verlangsamen. Eine meiner Regeln ist, dass IQueryable auf View nicht unterstützt wird.

Verwandte Themen