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と予想されますが、代わりにタイプIQueryableです(クエリは式ツリーに変換されますが、Linq-to-オブジェクトクエリは基本的に遅延メソッド呼び出しに変換されるため、式ツリー(によって作成された)をメソッド呼び出しに変換しようとしても機能しません。前述のように、これはC#の観点からは混乱を招きます)。 searchIEnumerable<T>IQueryable<T>context.Contacts

また、Queryable演算子がクエリを構築する方法は、を呼び出すことです。IQueryProvider<T>.CreateQueryこれにより、式ツリーIQueryable<T>が新しいオブジェクトを構築します。これは、どういうわけか、演算子がそれ自体で式ツリーIEnumerable<T>.TakeWhileを構築することを知っている必要があるか(そうではない)、または呼び出すことができる必要があることを意味しませんか?IQueryProvider<T>.CreateQuery

私の仮定が間違っていると確信しているので、誰かが前のクエリがどのようにしてIQueryable<T>代わりに型の結果を返すことができるのか説明できますIEnumerable<T>か?

前もって感謝します

4

2 に答える 2

1

Queryable.TakeWhileEnumerable.TakeWhileがあります

于 2012-10-29T19:07:10.667 に答える
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)
    {

    }
}

上記は機能します。私の推測では、null である 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 に答える