5

我正在从这里尝试 PagedList.Mvc 库

https://github.com/TroyGoode/PagedList

有这个用法示例

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

MyProductDataSource.FindAllProducts() 的典型实现;是沿着

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

这当然有 InvalidOperationException() 和 DBContext is already dispose 消息

寻找关于如何返回 IQueryable 的最佳实践,可以在这里毫无问题地使用?

4

2 回答 2

4

好的做法是使用 IoC 容器根据 HTTP 请求保持 DbContext 的生命周期,大多数 IoC 容器都支持 HttpRequest 生命周期。

IQueryable因此,您可以利用允许您在上层使用的 DbContext 范围。

我喜欢哪两个 IoC 容器的更多信息:autofacninject

autofac如何在这里支持 MVC

或者NInject如何在这里支持 MVC

如果你是 IoC 容器的新手,你会建议你看看Martin Flower的依赖注入的基本概念。然后继续使用您选择的 IoC 容器之一。

但是,您需要非常小心如何使用IQueryable以及应该停止支持它的哪一层。如果没有,后面的魔鬼,实体框架的延迟加载会降低性能。我的规则之一是不支持IQueryableView。

于 2013-05-08T18:03:27.307 回答
3

您需要“向上移动”数据上下文的范围:

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

然后在更大的范围内创建上下文:

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

    var pageNumber = page ?? 1;
    var onePageOfProducts = products.ToPagedList(pageNumber, 25);
}
于 2013-05-08T18:00:08.760 回答