列挙型をAsyncEnumerableにするにはどうすればよいですか?

.net c# entity-framework-core linq

質問

私は、Entity Frameworkコアで利用可能な非同期拡張メソッドを使用するいくつかのコードを持っています:

public async Task<MyResult> DoQuery<T>(IQueryable<T> queryable)
{
    var count = await queryable.CountAsync();
    var firstItems = await queryable
        .Take(5)
        .ToArrayAsync();

    return new MyResult(count, firstItems);
}

この機能は、 IQueryableがEFから直接提供されている場合にIQueryableです。また、LINQからオブジェクトへの「クエリ」に対していくつかのロジックを実行するために、このコードを再利用したいと考えました。

var evens = Enumerable.Range(0, 10).Where(i => i % 2 == 0);
var result = DoQuery(evens.AsQueryable());

これは失敗します(あまり驚くことではありません)。

System.InvalidOperationException:ソースIQueryableのプロバイダがIAsyncQueryProviderを実装していません。 Entity Frameworkの非同期操作では、IEntityQueryProviderを実装するプロバイダのみを使用できます。

リファクタが順番になっているようですが、私は不思議です:単純な列挙型をCountAsync同期的に扱う "ダミーの" AsyncEnumerableまたはAsyncQueryableする方法はCountAsyncますか?

受け入れられた回答

非同期クエリを処理するには、メモリ内のDbAsyncQueryProviderを作成する必要があります。 ここでそれを行う方法の詳細な説明があります非同期クエリを使用したテストに関する部分までスクロールします。以下はそのリンクからコピー&貼り付けられたコードです:

using System.Collections.Generic; 
using System.Data.Entity.Infrastructure; 
using System.Linq; 
using System.Linq.Expressions; 
using System.Threading; 
using System.Threading.Tasks; 

namespace TestingDemo 
{ 
    internal class TestDbAsyncQueryProvider<TEntity> : IDbAsyncQueryProvider 
    { 
        private readonly IQueryProvider _inner; 

        internal TestDbAsyncQueryProvider(IQueryProvider inner) 
        { 
            _inner = inner; 
        } 

        public IQueryable CreateQuery(Expression expression) 
        { 
            return new TestDbAsyncEnumerable<TEntity>(expression); 
        } 

        public IQueryable<TElement> CreateQuery<TElement>(Expression expression) 
        { 
            return new TestDbAsyncEnumerable<TElement>(expression); 
        } 

        public object Execute(Expression expression) 
        { 
            return _inner.Execute(expression); 
        } 

        public TResult Execute<TResult>(Expression expression) 
        { 
            return _inner.Execute<TResult>(expression); 
        } 

        public Task<object> ExecuteAsync(Expression expression, CancellationToken cancellationToken) 
        { 
            return Task.FromResult(Execute(expression)); 
        } 

        public Task<TResult> ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken) 
        { 
            return Task.FromResult(Execute<TResult>(expression)); 
        } 
    } 

    internal class TestDbAsyncEnumerable<T> : EnumerableQuery<T>, IDbAsyncEnumerable<T>, IQueryable<T> 
    { 
        public TestDbAsyncEnumerable(IEnumerable<T> enumerable) 
            : base(enumerable) 
        { } 

        public TestDbAsyncEnumerable(Expression expression) 
            : base(expression) 
        { } 

        public IDbAsyncEnumerator<T> GetAsyncEnumerator() 
        { 
            return new TestDbAsyncEnumerator<T>(this.AsEnumerable().GetEnumerator()); 
        } 

        IDbAsyncEnumerator IDbAsyncEnumerable.GetAsyncEnumerator() 
        { 
            return GetAsyncEnumerator(); 
        } 

        IQueryProvider IQueryable.Provider 
        { 
            get { return new TestDbAsyncQueryProvider<T>(this); } 
        } 
    } 

    internal class TestDbAsyncEnumerator<T> : IDbAsyncEnumerator<T> 
    { 
        private readonly IEnumerator<T> _inner; 

        public TestDbAsyncEnumerator(IEnumerator<T> inner) 
        { 
            _inner = inner; 
        } 

        public void Dispose() 
        { 
            _inner.Dispose(); 
        } 

        public Task<bool> MoveNextAsync(CancellationToken cancellationToken) 
        { 
            return Task.FromResult(_inner.MoveNext()); 
        } 

        public T Current 
        { 
            get { return _inner.Current; } 
        } 

        object IDbAsyncEnumerator.Current 
        { 
            get { return Current; } 
        } 
    } 
}


Related

ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ