2013-05-08 14 views
5

Próbuję bibliotekę PagedList.Mvc stądJak zwrócić IQueryable <T> do dalszych zapytań

https://github.com/TroyGoode/PagedList

który ma tę próbę użycia

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 

typowe implmentations z MyProductDataSource.FindAllProducts (); są wzdłuż linii

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

co oczywiście ma InvalidOperationException() i DBContext jest już umieszczona wiadomość

Szukasz najlepszych praktyk dotyczących sposobu, aby powrócić IQueryable który może być używany tutaj bez problemów?

+0

To NIE jest typowa implementacja. Zazwyczaj wstrzykujesz kontekst do klasy repozytorium, co oznacza, że ​​nie upuszczasz go na poziomie metody. –

+0

@WiktorZychla Nie zgadzam się. Obie są przydatnymi implementacjami. Kiedy możliwe jest lokalne dostosowanie kontekstu do metody, jest to do przyjęcia, ale gdy generowanie zapytania wykracza poza zakres tej metody, co nie jest możliwe, w takich przypadkach należy dostosować zakres kontekstu, na przykład że tam, gdzie jest, obejmuje czas życia tego zapytania. Programiści powinni być w stanie zrozumieć, jaki jest okres istnienia danego zapytania i zakres kontekstu, aby był na tym samym "poziomie", nie więcej, nie mniej. – Servy

+0

@Servy: prawda, ale w większości przypadków okres istnienia twojego kontekstu to "per-http-context". Zauważ, że taguje to pytanie za pomocą asp.net.To, co mówisz, jest częścią ogólnej teorii, potrzebuje dokładnych wskazówek do swojego konkretnego scenariusza asp.net. –

Odpowiedz

3

trzeba „przejść się” zakres swojego kontekstu danych:

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

następnie utworzyć kontekst w większym zakresie:

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

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

Alternatywą byłoby wstrzyknięcie kontekstu do źródła danych zamiast do każdej z nich. –

+0

@WiktorZychla Chodzi o to, że czas życia kontekstu musi zostać zwiększony, aby przekroczyć okres ważności zapytania, jak wysoko należy osiągnąć to, co może oczywiście różnić się w zależności od zapytania. Być może musi znajdować się w zasięgu tego obiektu, lub nie. – Servy

+0

Myślę, że to powinno być IQueryable

4

Dobrą praktyką jest, aby zachować żywotność DbContext jako na żądanie HTTP przy użyciu kontenera IoC, większość kontenerów IoC obsługuje okres życia HttpRequest.

Dzięki temu można korzystać z zakresu DbContext, który umożliwia korzystanie z wyższej warstwy na poziomie IQueryable.

Więcej informacji których dwa kontenery IoC Lubię: autofac i ninject.

Jak autofac obsługuje MVC w here

Albo jak NInject obsługuje MVC w here

Jeśli jesteś nowy na IoC kontenera, proponujesz należy wziąć wyglądać podstawowe pojęcia dependency injection Martin Flower. Następnie wybierz jeden z kontenerów IoC, które wybierzesz.

Musisz jednak bardzo uważać, aby korzystać z IQueryable i której warstwy powinieneś przestać wspierać. Jeśli nie, diabeł z tyłu, leniwy ładowanie ze struktury encji spowolni działanie. Jedną z moich zasad jest brak obsługi IQueryable w widoku.

Powiązane problemy