1

我知道下一个查询会引发异常,因为IQueryable<>提供程序不支持Enumerable.TakeWhile扩展方法。

        IQueryable<Contact> search = context.Contacts.TakeWhile(q => q.ContactID > 10);
        foreach(var q in search); // exception

但是,如果我尝试从 C# 的角度理解前面的查询,就会感到困惑。

由于要在上面的链中调用的最后一个 Linq 方法是Linq-to-Objects TakeWhile,我希望search变量是 type IEnumerable<T>,但它是 IQueryable 类型(我知道IQueryable<T>查询被转换为表达式树,而Linq-to-对象查询本质上转换为延迟方法调用,因此尝试将表达式树(由创建context.Contacts)转换为方法调用是行不通的。如前所述,从 C# 的角度来看,这让我感到困惑)。

此外,Queryable运算符构建查询的方式是调用 on IQueryProvider<T>.CreateQuery,给定表达式树构建新IQueryable<T>对象。这是否意味着IEnumerable<T>.TakeWhile操作员必须知道以某种方式自己构建表达式树(它不知道)或必须能够调用IQueryProvider<T>.CreateQuery

我很确定我的假设是错误的,所以有人可以解释一下前面的查询如何能够返回 type 的结果IQueryable<T>而不是IEnumerable<T>

先感谢您

4

2 回答 2

1

IQueryable<T>.TakeWhile()返回 IQueryable<T>

IEnumerable<T>.TakeWhile()返回 IEnumerable<T>

[Test]
public void TakeWhileTest()
{
    List<int> ints = new List<int> {1, 2, 3, 4};
    var enumerable = ints.AsEnumerable().TakeWhile(x => x < 3);
    Assert.IsNotInstanceOf<IQueryable<int>>(enumerable);
    foreach (var i in enumerable)
    {

    }
    IQueryable<int> queryable = ints.AsQueryable().TakeWhile(x => x < 3);
    Assert.IsInstanceOf<IQueryable<int>>(queryable);
    foreach (var i in queryable)
    {

    }
}

以上有效,我的猜测是您尝试从 aq 获取 q.ContactId 为空。你可以试试这个(并跳过 TakeWhile):

foreach (var contact in context.Contacts)
{
    if (contact.ContactID > 10)
        break;
    //Do your stuff here
}
于 2012-10-29T19:06:40.040 回答
1

有一个Queryable.TakeWhile和一个Enumerable.TakeWhile

于 2012-10-29T19:07:10.667 回答