C# 如何将可枚举转换为异步可枚举?
我有一些代码使用Entity Framework Core中可用的异步扩展方法:C# 如何将可枚举转换为异步可枚举?,c#,.net,linq,entity-framework-core,C#,.net,Linq,Entity Framework Core,我有一些代码使用Entity Framework Core中可用的异步扩展方法: public async Task<MyResult> DoQuery<T>(IQueryable<T> queryable) { var count = await queryable.CountAsync(); var firstItems = await queryable .Take(5) .ToArrayAsync();
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);
}
这失败了(这并不奇怪):
System.InvalidOperationException:源IQueryable的提供程序未实现IAsyncQueryProvider。只有实现IEntityQueryProvider的提供程序才能用于实体框架异步操作
看起来重构已经准备好了,但我很好奇:有没有办法将一个普通的可枚举文件转换成一个同步处理
CountAsync
的“虚拟”AsyncEnumerable
或AsyncQueryable
异步查询文件?您需要创建一个内存中的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; }
}
}
}
使用System.Collections.Generic;
使用System.Data.Entity.Infrastructure;
使用System.Linq;
使用System.Linq.Expressions;
使用系统线程;
使用System.Threading.Tasks;
命名空间测试演示
{
内部类TestDbAsyncQueryProvider:IDbAsyncQueryProvider
{
私有只读IQueryProvider\u内部;
内部测试DbaSyncQueryProvider(IQueryProvider内部)
{
_内部=内部;
}
公共IQueryable CreateQuery(表达式)
{
返回新的TestDbAsyncEnumerable(表达式);
}
公共IQueryable CreateQuery(表达式)
{
返回新的TestDbAsyncEnumerable(表达式);
}
公共对象执行(表达式)
{
返回_inner.Execute(表达式);
}
公共TResult执行(表达式)
{
返回_inner.Execute(表达式);
}
公共任务ExecuteAsync(表达式表达式,CancellationToken CancellationToken)
{
返回Task.FromResult(执行(表达式));
}
公共任务ExecuteAsync(表达式表达式,CancellationToken CancellationToken)
{
返回Task.FromResult(执行(表达式));
}
}
内部类TestDbAsyncEnumerable:EnumerableQuery、IDbAsyncEnumerable、IQueryable
{
公共TestDbAsyncEnumerable(IEnumerable enumerable)
:基本(可枚举)
{ }
公共TestDbAsyncEnumerable(表达式)
:base(表达式)
{ }
公共IDbAsyncEnumerator GetAsyncEnumerator()
{
返回新的TestDbAsyncEnumerator(this.AsEnumerable().GetEnumerator());
}
IDBSyncEnumerator IDBSyncEnumeratable.GetAsyncEnumerator()
{
返回GetAsyncEnumerator();
}
IQueryProvider IQueryable.Provider
{
获取{返回新的TestDbAsyncQueryProvider(this);}
}
}
内部类TestDbAsyncEnumerator:IDbAsyncEnumerator
{
私有只读IEnumerator\u内部;
公共TestDbAsyncEnumerator(IEnumerator内部)
{
_内部=内部;
}
公共空间处置()
{
_depose();
}
公共任务MoveNextAsync(CancellationToken CancellationToken)
{
返回Task.FromResult(_inner.MoveNext());
}
公共电流
{
获取{return}inner.Current;}
}
对象IDbAsyncEnumerator.Current
{
获取{返回当前;}
}
}
}
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; }
}
}
}