AsQueryable()的目的是什么?

Oce*_*t20 94 .net c# linq ienumerable iqueryable

是的目的AsQueryable()只是让你可以围绕传递IEnumerable到所期望的方法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();
}
Run Code Online (Sandbox Code Playgroud)

或者它实际上是否使它做了不同的事情:

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();
Run Code Online (Sandbox Code Playgroud)

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

Ser*_*rvy 58

主要有一些用途.

  1. 如其他答案中所述,您可以使用它来使用内存数据源模拟可查询数据源,以便您可以更轻松地测试最终将在非可枚举的数据源上使用的方法IQueryable.

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

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

  • 鉴于`IQueryable <T>`来自`IEnumerable <T>`你能解释一下你所说的"非可枚举的IQueryable"吗? (3认同)
  • @Dai它指的是一个`IQueryable`,它不仅仅是一个包裹的`IEnumerable`,它实际上利用了`IQueryable`的附加功能. (2认同)

小智 11

我对AsQueryable最有效的案例是单元测试.说我有以下有点人为的例子

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

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


   public IQueryable<Widget> Get()
   {
      return WidgetRepository.Retrieve();
   }
}
Run Code Online (Sandbox Code Playgroud)

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

[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));
}
Run Code Online (Sandbox Code Playgroud)

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

我会对应用程序代码中使用它感兴趣.


Sco*_*ott 9

正如sanjuro所指出的,AsQueryable()的目的在使用Linq To Objects和Linq To SQL使用AsQueryable进行了解释.特别是,文章指出,

这在真实的单词场景中提供了极好的好处,在这些场景中,您在返回IQ的可执行文件的实体上有某些方法,并且某些方法返回List.但是你有业务规则过滤器需要应用于所有集合,无论集合是作为T的IQueryable还是从Tn的IEnumerable返回的.从性能角度来看,你真的想利用在数据库上执行业务过滤器该集合实现IQueryable,否则回退以使用Linq在内存中应用业务过滤器来对象委托的实现.


san*_*uro 7

AsQueryable() 的目的在这篇文章中得到了很好的解释,将 AsQueryable 与 Linq To Objects 和 Linq To SQL 结合使用

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

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

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