C# AsQueryable() 的目的是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17366907/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 09:18:57  来源:igfitidea点击:

What is the purpose of AsQueryable()?

c#.netlinqienumerableiqueryable

提问by Ocelot20

Is the purpose of AsQueryable()just so you can pass around an IEnumerableto methods that might expect IQueryable, or is there a useful reason to represent IEnumerableas IQueryable? For example, is it supposed to be for cases like this:

目的是AsQueryable()为了让您可以传递IEnumerable可能期望的to 方法IQueryable,还是有一个有用的理由来表示IEnumerableIQueryable?例如,它是否应该用于这样的情况:

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();
}

Or does it actually make it do something different:

或者它真的让它做一些不同的事情:

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();

Do the IQueryableversions of these extension methods just build up an Expression that ends up doing the same thing once its executed? My main question is, whats a real use case for using AsQueryable?

IQueryable这些扩展方法的版本是否只是构建了一个表达式,一旦执行,它最终会做同样的事情?我的主要问题是,使用的真正用例是什么AsQueryable

采纳答案by Servy

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. You can write helper methods for manipulating collections that can apply to either in-memory sequences or external data sources. If you write your help methods to use IQueryableentirely you can just use AsQueryableon all enumerables to use them. This allows you to avoid writing two separate versions of very generalized helper methods.

  3. It allows you to change the compile time type of a queryable to be an IQueryable, rather than some more derived type. In effect; you'd use it on an IQueryableat the same times that you'd use AsEnumerableon an IEnumerable. You might have an object that implements IQueryablebut that also has an instance Selectmethod. If that were the case, and you wanted to use the LINQ Selectmethod, you'd need to change the compile time type of the object to IQueryable. You could just cast it, but by having an AsQueryablemethod you can take advantage of type inference. This is simply more convenient if the generic argument list is complex, and it is actually necessaryif any of the generic arguments are anonymous types.

  1. 正如其他答案中提到的,您可以使用它来模拟使用内存中数据源的可查询数据源,以便您可以更轻松地测试最终将在基于不可枚举的IQueryable.

  2. 您可以编写辅助方法来操作可应用于内存中序列或外部数据源的集合。如果您编写IQueryable完全使用的帮助方法,则可以AsQueryable在所有可枚举项上使用它们。这允许您避免编写非常通用的辅助方法的两个单独版本。

  3. 它允许您将可查询的编译时类型更改为IQueryable,而不是一些更派生的类型。有效; 您将在 . 上使用它IQueryable的同时AsEnumerableIEnumerable. 您可能有一个实现IQueryable但也有一个实例Select方法的对象。如果是这种情况,并且您想使用 LINQSelect方法,则需要将对象的编译时类型更改为IQueryable. 您可以直接转换它,但是通过拥有一种AsQueryable方法,您可以利用类型推断。如果泛型参数列表很复杂,这只是更方便,如果任何泛型参数是匿名类型,这实际上是必要的

回答by Tigran

Interface IQueryablequoting documentation:

接口IQueryable引用文档:

The IQueryable interface is intended for implementation by query providers.

IQueryable 接口旨在供查询提供程序实现。

So for someone that intends to make its datastracture queryable in .NET, that datastructure that not necessary can be enumerated or have valid enumerator.

因此,对于打算在 .NET 中使其数据结构可查询的人,可以枚举不需要的数据结构或具有有效的 enumerator

IEnumeratoris an interface for iterating and processing stream of datainstead.

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

回答by chris

The most valid case I have for AsQueryable is unit testing. Say I have the following somewhat contrived example

我对 AsQueryable 的最有效案例是单元测试。说我有以下有点做作的例子

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

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


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

and I want to write a unit test to make sure the controller passes back the results returned from the repository. It'd look something like this:

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

[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));
}

where really, all the AsQueryable() method allows me to do is satisfy the compiler when setting up a mock.

实际上,所有 AsQueryable() 方法允许我做的是在设置模拟时满足编译器。

I'd be interested where this is used in application code though.

不过,我会对在应用程序代码中使用它的地方感兴趣。

回答by sanjuro

The purpose of AsQueryable() is greatly explained in this article Using AsQueryable With Linq To Objects And Linq To SQL

AsQueryable() 的目的在这篇文章中详细解释了在Linq To Objects 和 Linq To SQL 中使用 AsQueryable

From Remarks section of MSDN Queryable.AsQueryable Method:

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

If the type of source implements IQueryable, AsQueryable(IEnumerable) returns it directly. Otherwise, it returns an IQueryable that executes queries by calling the equivalent query operator methods in Enumerable instead of those in Queryable.

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

Thats is exactly what is mentioned and used in above article. In your example, it depends on what is orderRepo.GetAll returning, IEnumerable or IQueryable(Linq to Sql). If it returns IQueryable, the Count() method will be executed on database otherwise it will be executed in memory. Look carefully at example in referenced article.

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

回答by Scott

As sanjuro noted, the purpose of AsQueryable() is explained in Using AsQueryable With Linq To Objects And Linq To SQL. In particular, the article states,

正如 sanjuro 所指出的,AsQueryable() 的目的在将 AsQueryable 与 Linq To Objects 和 Linq To SQL一起使用中进行了解释。文章特别指出,

This offers an excellent benefits in real word scenarios where you have certain methods on an entity that return an IQueryable of T and some methods return List. But then you have business rule filter that needs to be applied on all the collection regardless if the collection is returned as IQueryable of T or IEnumerable of T. From a performance stand point, you really want to leverage executing the business filter on the database if the collection implements IQueryable otherwise fall back to apply the business filter in memory using Linq to object implementation of delegates.

这在实际场景中提供了极好的好处,其中实体上的某些方法返回 T 的 IQueryable 并且某些方法返回列表。但是,您有需要应用于所有集合的业务规则过滤器,无论集合是作为 T 的 IQueryable 还是 T 的 IEnumerable 返回。从性能的角度来看,您真的希望利用在数据库上执行业务过滤器,如果集合实现 IQueryable 否则回退以使用 Linq 将内存中的业务过滤器应用于委托的对象实现。