AsQueryable()的目的是什么?

AsQueryable()的用途是否只是为了能够将 IEnumerable传递给可能期望使用 IQueryable的方法,或者是否有一个有用的理由将 IEnumerable表示为 IQueryable?例如,它是否应该用于这样的情况:

IEnumerable<Order> orders = orderRepo.GetAll();


// I don't want to create another method that works on IEnumerable,
// so I convert it here.
CountOrders(orders.AsQueryable());


public static int CountOrders(IQueryable<Order> ordersQuery)
{
return ordersQuery.Count();
}

或者它实际上使它做一些不同的事情:

IEnumerable<Order> orders = orderRepo.GetAll();
IQueryable<Order> ordersQuery = orders.AsQueryable();


IEnumerable<Order> filteredOrders = orders.Where(o => o.CustomerId == 3);
IQueryable<Order> filteredOrdersQuery = ordersQuery.Where(o => o.CustomerId == 3);


// Are these executed in a different way?
int result1 = filteredOrders.Count();
int result2 = filteredOrdersQuery.Count();

这些扩展方法的 IQueryable版本是否只是构建了一个一旦执行就会执行相同操作的表达式?我的主要问题是,使用 AsQueryable的真正用例是什么?

108630 次浏览

接口 IQueryable报价文件:

IQueryable 接口旨在通过查询实现 供应商。

因此,对于那些打算在.NET 中使其数据结构具有可查询性的人来说,这种数据结构 不需要的枚举数或具有有效枚举数

IEnumerator是用于迭代和处理 数据流数据流的接口。

对于 AsQueryable,最有效的例子是单元测试

public interface IWidgetRepository
{
IQueryable<Widget> Retrieve();
}


public class WidgetController
{
public IWidgetRepository WidgetRepository {get; set;}




public IQueryable<Widget> Get()
{
return WidgetRepository.Retrieve();
}
}

我想编写一个单元测试,以确保控制器返回从存储库返回的结果。它看起来像这样:

[TestMethod]
public void VerifyRepositoryOutputIsReturned()
{
var widget1 = new Widget();
var widget2 = new Widget();
var listOfWidgets = new List<Widget>() {widget1, widget2};
var widgetRepository = new Mock<IWidgetRepository>();
widgetRepository.Setup(r => r.Retrieve())
.Returns(listOfWidgets.AsQueryable());
var controller = new WidgetController();
controller.WidgetRepository = widgetRepository.Object;


var results = controller.Get();


Assert.AreEqual(2, results.Count());
Assert.IsTrue(results.Contains(widget1));
Assert.IsTrue(results.Contains(widget2));
}

实际上,AsQueryable ()方法允许我做的只是在设置 mock 时满足编译器的要求。

不过,我对这种方法在应用程序代码中的用途很感兴趣。

AsQueryable ()的用途在本文 在对象和 SQL 中使用 AsQueryable中得到了很好的解释

来自 MSDN Queryable.AsQueryable 的备注部分方法:

如果源的类型实现了 IQueryable,AsQueryable (IEnumable)将直接返回它。否则,它返回一个 iQueryable,通过在 Enumerable 而不是在 Queryable 调用等效的查询运算符方法来执行查询。

这正是上面文章中提到和使用的。 在您的示例中,它取决于 orderRepo 是什么。GetAll 返回、 IEnumable 或 IQueryable (Linq 到 Sql)。如果返回 IQueryable,Count ()方法将在数据库上执行,否则将在内存中执行。仔细查看参考文章中的例子。

There are a few main uses.

  1. As mentioned in other answers, you can use it to mock a queryable data source using an in-memory data source so that you can more easily test methods that will eventually be used on a non-enumerable based IQueryable.

  2. 您可以编写帮助器方法来操作可以应用于内存序列或外部数据源的集合。如果您编写了完全使用 IQueryable的帮助方法,那么只需在所有可枚举数上使用 AsQueryable即可。这使您可以避免编写两个非常广义的 helper 方法的独立版本。

  3. 它允许您将可查询的编译时类型更改为 IQueryable,而不是更多的派生类型。实际上,在 IQueryable上使用它的时间与在 IEnumerable上使用 AsEnumerable的时间相同。您可能有一个实现 IQueryable的对象,但是它也有一个实例 Select方法。如果是这种情况,并且您希望使用 LINQSelect方法,则需要将对象的编译时类型更改为 IQueryable。您可以只进行强制转换,但是通过使用 AsQueryable方法,您可以利用类型推断的优势。如果泛型参数列表比较复杂,而且如果任何泛型参数都是匿名类型,那么它实际上就是 有需要

正如 sanjuro 所指出的,AsQueryable ()的用途在 在对象和 SQL 中使用 AsQueryable中有解释,

这在实际的单词场景中提供了极大的好处,在这些场景中,您在一个实体上拥有某些方法,这些方法返回一个 T 的 IQueryable,而一些方法返回 List。但是,无论集合返回的是 T 的 IQueryable 还是 T 的 IEnumable,您都需要对所有集合应用业务规则过滤器。从性能角度来看,如果集合实现了 IQueryable,那么您确实希望在数据库上执行业务过滤器,否则就会退回到使用 Linq 对委托的对象实现应用内存中的业务过滤器。