我应该从DAL返回IEnumerable <T>还是IQueryable <T>?

Arm*_*est 38 datacontext data-access-layer iqueryable linq-to-sql

我知道这可能是意见,但我正在寻找最佳实践.

据我所知,IQueryable<T>实现IEnumerable<T>,所以在我的DAL中,我目前有方法签名,如下所示:

IEnumerable<Product> GetProducts();
IEnumerable<Product> GetProductsByCategory(int cateogoryId);
Product GetProduct(int productId);
Run Code Online (Sandbox Code Playgroud)

我应该IQueryable<T>在这里使用吗?

这两种方法的优点和缺点是什么?

请注意,我打算使用Repository模式,所以我将有一个这样的类:

public class ProductRepository {

    DBDataContext db = new DBDataContext(<!-- connection string -->);

    public IEnumerable<Product> GetProductsNew(int daysOld) {
        return db.GetProducts()
          .Where(p => p.AddedDateTime > DateTime.Now.AddDays(-daysOld ));
    }
}
Run Code Online (Sandbox Code Playgroud)

我应该改变我IEnumerable<T>IQueryable<T>吗?一个或另一个有哪些优点/缺点?

Jim*_*amb 52

这取决于你想要的行为.

  • 返回IList <T>告诉调用者他们已经收到了他们请求的所有数据
  • 返回一个IEnumerable <T>告诉调用者他们需要迭代结果并且它可能被延迟加载.
  • 返回IQueryable <T>告诉调用者结果由Linq提供程序支持,该提供程序可以处理某些类的查询,从而减轻调用者的负担以形成高性能查询.

虽然后者为调用者提供了很大的灵活性(假设您的存储库完全支持它),但它是最难测试的,并且可以说是最不确定的.


Rya*_*yan 8

还有一件事需要考虑:您的分页/排序支持在哪里?如果您在存储库中提供分页支持,则返回IEnumerable<T>很好.如果您在存储库之外进行分页(例如在控制器或服务层中),那么您真的想要使用,IQueryable<T>因为您不希望在分页之前将整个数据集加载到内存中.


Mik*_* M. 5

HUUUUGGGE的区别.我看到了这一点.

在它到达数据库之前构建一个IQueryable.一旦调用了一个eager函数(例如.ToList()),IQueryable只会命中DB,或者你实际上试图将值拉出来.IQueryable =懒惰.

IEnumerable将立即对数据库执行lambda.IEnumerable =渴望.

关于哪个与Repository模式一起使用,我相信它很渴望.我经常看到IList被传递,但其他人需要为你解决这个问题.编辑 - 您通常会看到IEnumerable而不是IQueryable,因为您不希望图层超过您的存储库A)确定数据库命中何时发生或B)将任何逻辑添加到存储库外的连接

有一个非常好的LINQ视频,我很喜欢它 - 它不仅仅是IEnumerable v IQueryable,它真的有一些奇妙的洞察力.

http://channel9.msdn.com/posts/matthijs/LINQ-Tips-Tricks-and-Optimizations-by-Scott-Allen/

  • IEnumerable并不一定渴望.Enumerable.Select返回一个懒惰的IEnumerable. (3认同)