代码之家  ›  专栏  ›  技术社区  ›  Armstrongest

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

  •  38
  • Armstrongest  · 技术社区  · 15 年前

    我知道这可能是我的观点,但我在寻找最佳实践。

    据我所知, IQueryable<T> 工具 IEnumerable<T> ,因此在我的DAL中,我当前有如下方法签名:

    IEnumerable<Product> GetProducts();
    IEnumerable<Product> GetProductsByCategory(int cateogoryId);
    Product GetProduct(int productId);
    

    我应该用吗 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 ));
        }
    }
    

    IEnumerable<T> IQueryable<T>

    4 回复  |  直到 12 年前
        1
  •  52
  •   Jim Lamb    15 年前

    这取决于你想要什么样的行为。

    • 返回
    • 返回 IEnumerable<T> 告诉调用者需要对结果进行迭代,结果可能会被延迟加载。
    • 返回 告诉调用者结果由可以处理某些查询类的Linq提供程序支持,这会给调用者带来形成性能查询的负担。

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

        2
  •  8
  •   Ryan    15 年前

    IEnumerable<T> 很好。如果您在存储库之外进行分页(如在控制器或服务层中),那么您真的想使用 IQueryable<T>

        3
  •  5
  •   Mike M.    15 年前

    霍乌格差异。我经常看到这个。

    至于使用哪种存储库模式,我相信这是迫切需要的。我通常看到ILists被通过,但是其他人需要为你解决这个问题。编辑-您通常会看到IEnumerable而不是IQueryable,因为您不希望层超过存储库A)确定何时发生数据库命中,或B)向存储库外部的连接添加任何逻辑

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

        4
  •  3
  •   Peter Willis    15 年前

    您可以使用IQueryable并接受有人可以创建一个场景 SELECT N+1 可能发生。这是一个缺点,另外一个事实是,您可能会在存储库上方的层中生成特定于存储库实现的代码。这样做的好处是,您允许在respository之外表达诸如分页和排序之类的委托常见操作,从而减轻了它的此类顾虑。如果您需要将数据与其他数据库表连接起来,那么它也更灵活,因为查询仍然是一个表达式,因此可以在将其解析为查询并命中数据库之前添加到。

    ToList() . 以分页和排序为例,需要将skip、take和sort表达式作为参数传递给存储库的方法,并使用这些参数仅返回一个结果窗口。这意味着存储库负责分页和排序,以及所有数据的投影。