I'm trying the PagedList.Mvc library from here
https://github.com/TroyGoode/PagedList
which has this usage sample
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
typical implmentations of MyProductDataSource.FindAllProducts(); are along the lines of
public IQuerable<T> MyProductDataSource.FindAllProducts()
{
using ( var ctx = new MyCtx() )
{
return ctx.MyList().Where( .... );
}
}
which of course has the InvalidOperationException() and DBContext is already disposed message
Looking for best practices on how to return IQueryable which can be used here without issues ?
If they add a where clause to a deferred IQueryable , you only have to send that data over the wire, not the entire result set. If you are using repository pattern - no, you should not return IQueryable.
IQueryable is executed. // // Returns: // A System.Type that represents the type of the element(s) that are returned when. // the expression tree associated with this object is executed.
The major difference between IQueryable and IEnumerable is that IQueryable executes query with filters whereas IEnumerable executes the query first and then it filters the data based on conditions.
IQueryable is faster than IEnumerable. In addition to Munesh Sharma's answer:IEnumerable loads data in-memory and then apply filters to it one by one but IQueryable apply filters all at once and return the result.
The good practice is to keep the lifetime of DbContext as per HTTP request by using IoC container, most of IoC containers support HttpRequest lifetime.
So you can leverage the scope of DbContext which allows you to use IQueryable
on upper layer.
More information which two IoC containers I like: autofac and ninject.
How autofac supports MVC in here
Or how NInject supports MVC in here
If you are new on IoC container, you would suggest you should take a look the basic concept of dependency injection from Martin Flower. Then go ahead with one of IoC container you choose.
But, you need to be very careful on how to use IQueryable
and which layer you should stop support it. If not, the devil on behind, lazy loading from entity framework will slow down the performance. One of my rule is do not support IQueryable
on View.
You need to "move up" the scope of your data context:
public IQueryable<T> MyProductDataSource.FindAllProducts(MyCtx context)
{
return context.MyList().Where( .... );
}
Then create the context at the larger scope:
using (var ctx = new MyCtx())
{
var products = MyProductDataSource.FindAllProducts(ctx);
var pageNumber = page ?? 1;
var onePageOfProducts = products.ToPagedList(pageNumber, 25);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With