c# – ToArrayAsync()抛出“源IQueryable未实现IAsyncEnumerable
我在ASP.NET Core上有一个MVC项目,我的问题与IQueryable和异步相关.我在IQueryable< T>中编写了以下搜索方法:
private IQueryable<InternalOrderInfo> WhereSearchTokens(IQueryable<InternalOrderInfo> query,SearchToken[] searchTokens) { if (searchTokens.Length == 0) { return query; } var results = new List<InternalOrderInfo>(); foreach (var searchToken in searchTokens) { //search logic,intermediate results are being added to `results` using `AddRange()` } return results.Count != 0 ? results.Distinct().AsQueryable() : query; } 我在方法ExecuteAsync()中调用它: public async Task<GetAllInternalOrderInfoResponse> ExecuteAsync(GetAllInternalOrderInfoRequest request) { //rest of the code if (searchTokens != null && searchTokens.Any()) { allInternalOrderInfo = WhereSearchTokens(allInternalOrderInfo,searchTokens); } var orders = await allInternalOrderInfo.Skip(offset).Take(limit).ToArrayAsync(); //rest of the code } 当我测试这个时,我在线上得到一个InvalidOperationException,我调用ToArrayAsync()
我已经将ToArrayAsync()更改为ToListAsync()但没有任何更改.我已经搜索了这个问题一段时间了,但已解决的问题主要与DbContext和实体创建有关.没有为此项目安装EntityFramework,最好不要因为应用程序架构而这样做.希望有人有任何想法在我的情况下做什么. 解决方法
如果您不打算改变您的设计 – 您有以下几种选择:
1)将AsQueryable更改为另一个返回IQueryable的方法,该方法也实现了IDbAsyncEnumerable.例如,您可以扩展EnumerableQuery(由AsQueryable返回): public class AsyncEnumerableQuery<T> : EnumerableQuery<T>,IDbAsyncEnumerable<T> { public AsyncEnumerableQuery(IEnumerable<T> enumerable) : base(enumerable) { } public AsyncEnumerableQuery(Expression expression) : base(expression) { } public IDbAsyncEnumerator<T> GetAsyncEnumerator() { return new InMemoryDbAsyncEnumerator<T>(((IEnumerable<T>) this).GetEnumerator()); } IDbAsyncEnumerator IDbAsyncEnumerable.GetAsyncEnumerator() { return GetAsyncEnumerator(); } private class InMemoryDbAsyncEnumerator<T> : IDbAsyncEnumerator<T> { private readonly IEnumerator<T> _enumerator; public InMemoryDbAsyncEnumerator(IEnumerator<T> enumerator) { _enumerator = enumerator; } public void Dispose() { } public Task<bool> MoveNextAsync(CancellationToken cancellationToken) { return Task.FromResult(_enumerator.MoveNext()); } public T Current => _enumerator.Current; object IDbAsyncEnumerator.Current => Current; } } 然后你改变 results.Distinct().AsQueryable() 至 new AsyncEnumerableQuery<InternalOrderInfo>(results.Distinct()) 之后,ToArrayAsync将不再抛出异常(显然你可以像AsQueryable一样创建自己的扩展方法). 2)更改ToArrayAsync部分: public static class EfExtensions { public static Task<TSource[]> ToArrayAsyncSafe<TSource>(this IQueryable<TSource> source) { if (source == null) throw new ArgumentNullException(nameof(source)); if (!(source is IDbAsyncEnumerable<TSource>)) return Task.FromResult(source.ToArray()); return source.ToArrayAsync(); } } 并使用ToArrayAsyncSafe而不是ToArrayAsync,如果IQueryable不是IDbAsyncEnumerable,它将回退到同步枚举.在你的情况下,这只发生在查询真的是内存列表而不是查询时,所以异步执行无论如何都没有意义. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |