Linq to sql 我是否应该返回IEnumerable<;T>;或IQueryable<;T>;从我父亲那里?

Linq to sql 我是否应该返回IEnumerable<;T>;或IQueryable<;T>;从我父亲那里?,linq-to-sql,datacontext,data-access-layer,iqueryable,Linq To Sql,Datacontext,Data Access Layer,Iqueryable,我知道这可能是一种观点,但我正在寻找最佳实践 据我所知,IQueryable实现了IEnumerable,因此在我的DAL中,我目前有如下方法签名: IEnumerable<Product> GetProducts(); IEnumerable<Product> GetProductsByCategory(int cateogoryId); Product GetProduct(int productId); IEnumerable GetProducts(); IEn

我知道这可能是一种观点,但我正在寻找最佳实践

据我所知,
IQueryable
实现了
IEnumerable
,因此在我的DAL中,我目前有如下方法签名:

IEnumerable<Product> GetProducts();
IEnumerable<Product> GetProductsByCategory(int cateogoryId);
Product GetProduct(int productId);
IEnumerable GetProducts();
IEnumerable GetProductsByCategory(int CategoryId);
产品GetProduct(int-productId);
我应该在这里使用
IQueryable

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

请注意,我计划使用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 ));
    }
}
公共类产品存储库{
DBDataContext db=新的DBDataContext();
公共IEnumerable GetProductsNew(int Daysaled){
return db.GetProducts()
.Where(p=>p.AddedDateTime>DateTime.Now.AddDays(-daysaled));
}
}

我是否应该将我的
IEnumerable
更改为
IQueryable
?这两者有什么优点/缺点?

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

在iQueryTable进入数据库之前,先建立它。IQueryable仅在调用了一个渴望函数(.ToList()例如)或您实际尝试提取值时才会命中DB。IQueryable=懒惰

IEnumerable将立即对DB执行lambda。IEnumerable=渴望

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

有一个非常好的LINQ视频,我非常喜欢——它不仅仅是IEnumerable v IQueryable,但它确实有一些奇妙的洞察力


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

  • 返回一个IList告诉调用者他们已经收到了他们请求的所有数据
  • 返回一个IEnumerable告诉调用者他们需要迭代结果,结果可能会被延迟加载
  • 返回一个IQueryable告诉调用者结果是由一个Linq提供程序支持的,该提供程序可以处理某些类的查询,这会给调用者带来形成性能查询的负担

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

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

另一种方法是锁定存储库,以便通过调用
ToList()
返回具体化的列表。以分页和排序为例,您需要将skip、take和sort表达式作为参数传递给存储库的方法,并使用这些参数仅返回一个结果窗口。这意味着存储库承担了分页和排序的责任,以及数据的所有投影


这有点像是一种判断,您是将linq的强大功能赋予您的应用程序,使其在存储库中的复杂性降低,还是控制您的数据访问。对我来说,这取决于与每个实体相关联的查询数量和实体组合,以及我想在哪里管理这种复杂性。

还有一件事需要考虑:您的分页/排序支持在哪里?如果您在存储库中提供分页支持,那么返回
IEnumerable
就可以了。如果您在存储库外部(如控制器或服务层)进行分页,那么您确实希望使用
IQueryable
,因为您不希望在分页之前将整个数据集加载到内存中。

请澄清,
ProductRepository
位于我的应用程序内部。。。鉴于DAL是一个单独的项目,我有一个参考。因此,我从我的应用程序调用存储库,存储库调用DAL项目中的DBDataContext类(包含所有通用方法),然后该类对数据库执行任何LinqToSQL。IEnumerable不一定是急切的。可枚举。选择返回一个惰性IEnumerable。很棒的视频。谢谢你!六羟甲基三聚氰胺六甲醚。。。有些事情需要考虑,马上。我总是把IList和IEnumerable放在一个桶里,但我更喜欢这个想法。