【问题标题】:Should I be specifying IQueryable over List in my interfaces?我应该在我的界面中指定 IQueryable 而不是 List 吗?
【发布时间】:2015-04-13 09:04:13
【问题描述】:

我想知道,在定义我的接口时,对于对象组,我是否应该更喜欢 IQueryable 而不是 List。或者也许 IEnumerable 更好,因为 IEnumerable 类型可以转换为 IQueryable 以用于 LINQ。

我在网上查看一门课程,它正在处理 EntityFramework,最好使用 IQueryable,因为 LINQ 使用它(好吧,还有更多,但现在可能并不重要)。 使用了下面的代码,这让我开始思考是否应该为我的对象组指定 IQueryable 而不是 List。

namespace eManager.Domain
{
    public interface IDepartmentDataSource
    {
        IQueryable<Employee> Employees { get; }
        IQueryable<Department> Departments { get; }
    }

如果我正在为调用存储库以获取员工的服务构建一个接口,我通常会指定

List <Employees> 

但这是最佳做法吗? IQueryable 会为实现我的接口的类提供更大的灵活性吗?如果他们不需要它(比如说他们只想要一个列表),那么必须导入 LINQ 的开销呢?我应该对这两个都使用 IEnumerable 吗?

【问题讨论】:

  • 您可能应该用“C#”标记您的问题以引起更多关注。
  • 哦,LINQ 实际上也很容易使用IEnumerable。区别在于您是要提供一组调用者可以使用的数据,还是要提供该数据的代理。就个人而言,我会选择IEnumerable / IList,除非你有特定的理由使用IQueryableIQueryable 让你的界面太宽了。让你的界面比“这里的所有员工,随心所欲”更紧密:)
  • 使用IQueryable 会给接口的实现者带来负担。仅当存在需要该接口的代码时,才有意义。是否有代码显示“我真的在这里需要IQueryable”?
  • @Dialectus 是的,这就是为什么我想知道 IEnumerable 是否是一个更好的选择。
  • 要回答您想知道的问题,人们必须知道是否存在尖叫“我真的需要IQueryable就在这里”的代码。只有你自己知道,所以只有你自己可以回答自己的问题。如果没有这样的代码,那就通过简化界面来减轻负担。

标签: c# interface ienumerable iqueryable


【解决方案1】:

IQueryable 接口实际上是对尚未执行的实体框架的查询。当你在IQueryable上调用ToList()First()FirstOrDefault()等时,Entity Framework会构造SQL查询并查询数据库。

IEnumerable 另一方面,“只是”集合上的枚举数。您可以使用它来过滤集合,但您可以使用 LINQ to Objects。 Entity Framework 在这里没有发挥作用。

回答您的问题:视情况而定。如果您希望存储库的客户端能够进一步自定义他们可以执行的查询,您应该公开IQueryable,但如果您希望在存储库中完全控制数据库的查询方式,您可以使用IEnumerable

我更喜欢使用IEnumerable,因为这不会在整个应用程序中泄露实体框架的使用。存储库负责数据库访问。优化 LINQ to EF 也更容易,因为查询只在存储库中。

【讨论】:

  • 从你所说的我觉得存储库应该使用 IQueryable 以便它可以使用 LINQ 进行查询。调用它的服务应该向其客户返回 IEnumerable。该服务应该对它的客户说“你已经向我询问了这些数据,这是 - 我已经完成了”。任何进一步的过滤都将由客户端完成 - 服务不在乎。
  • 是的,存储库隐式使用 IQueryable,因为这是 Entity Framework 公开的。当您从存储库返回项目集合时,您可以从存储库返回一个 IEnumerable。为确保您不会从存储库中公开 IQueryable,您应该在 IQueryable 上调用 ToList(),以便执行 SQL 查询。
【解决方案2】:

我通常做的是让存储库返回IQueryable。然后在 BL 中指定IEnumerableIQueryble。了解IQuerybleIEnumerable 之间的主要区别很重要。

假设您将数据提取到 IEnumerable IEnumerable employees=this.repository.GetAll(); 现在假设这个特定的功能只需要21岁以上的员工,其他的根本不需要。

你会这样做: employees.Where(a=&gt;a.Age&gt;21) 在这种情况下,原始查询将被加载到内存中,然后将应用 Where。

现在假设您更改了将数据提取到 IQueryable 中的函数 IQueryable employees=this.repository.GetAll(); employees.Where(a=&gt;a.Age&gt;21) 这一次,当您使用 Where 子句修改查询时,整个查询将在数据库中执行(如果可能),您只会从数据库中获取年龄超过 21 岁的员工。

在 IEnumerable 的情况下,您将从数据库中获取所有员工,然后他们将在内存中过滤以满足 where 条件。

使用 IEnumerable、IList 还是其他? 如果您知道将在集合上执行哪些操作,则可以轻松选择要使用的接口。基本上,如果您只对集合进行迭代,您将使用 IEnumerable。如果要进行更多操作,则需要选择合适的接口。在复数视野中有很好的 .NET 集合视频。

【讨论】:

    猜你喜欢
    • 2012-06-23
    • 1970-01-01
    • 2011-02-25
    • 2010-10-17
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 2011-03-02
    • 2010-09-28
    相关资源
    最近更新 更多