.NET Framework 4.7.2 Enumerable扩展迁移至.NET 6的适配疑问
.NET Framework 4.7.2 迁移至.NET 6:AsyncQueryable扩展代码的处理方案
一、核心结论:这个代码在.NET6里几乎不需要保留
原代码是为了解决**.NET Framework早期版本(如EF6及之前)中IQueryable不原生支持异步枚举**的问题,通过实现EF专属的IDbAsyncEnumerable系列接口模拟异步操作。但在.NET6环境下:
- 若使用EF Core,其
IQueryable<T>原生实现了IAsyncEnumerable<T>,直接支持ToListAsync()、FirstOrDefaultAsync()等异步方法,无需额外包装。 - 对于内存集合(如
List<T>),可通过NuGet安装System.Linq.Async包,直接调用source.ToAsyncEnumerable()获取标准的IAsyncEnumerable<T>实现,无需自行编写包装类。 - 仅当维护自定义Repository且有特殊异步查询需求时,才可能需要类似逻辑,但这类场景极少。
二、极端场景下的代码转换(若必须保留)
如果因历史代码依赖必须保留类似功能,需对原代码做如下修改(移除EF6专属接口,适配.NET6标准API):
简化后的适配代码
using System.Linq.Expressions; using System.Runtime.CompilerServices; public static class EnumerableExtensions { public static IQueryable<T> AsAsyncQueryable<T>(this IEnumerable<T> source) { return new AsyncQueryableWrapper<T>(source.AsQueryable()); } public static IQueryable<T> AsAsyncQueryable<T>(this IQueryable<T> source) { return new AsyncQueryableWrapper<T>(source); } } internal class AsyncQueryableWrapper<T> : IQueryable<T>, IAsyncEnumerable<T> { private readonly IQueryable<T> _source; public AsyncQueryableWrapper(IQueryable<T> source) { _source = source; } public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default) { return new AsyncEnumerator<T>(_source.GetEnumerator()); } public IEnumerator<T> GetEnumerator() { return _source.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); public Expression Expression => _source.Expression; public Type ElementType => _source.ElementType; public IQueryProvider Provider => _source.Provider; } internal class AsyncEnumerator<T> : IAsyncEnumerator<T> { private readonly IEnumerator<T> _inner; public AsyncEnumerator(IEnumerator<T> inner) { _inner = inner; } public ValueTask<bool> MoveNextAsync() { return ValueTask.FromResult(_inner.MoveNext()); } public T Current => _inner.Current; public ValueTask DisposeAsync() { _inner.Dispose(); return ValueTask.CompletedTask; } }
关键修改点
- 移除所有EF6专属的
IDbAsyncEnumerable、IDbAsyncEnumerator、IDbAsyncQueryProvider类型,改用.NET6标准的IAsyncEnumerable<T>和IAsyncEnumerator<T>接口 - 适配
IAsyncEnumerator<T>的规范:MoveNextAsync返回ValueTask<bool>,新增DisposeAsync方法返回ValueTask - 移除自定义查询提供器,直接复用原
IQueryable的Provider,因为.NET6标准查询提供器已支持异步相关逻辑
三、推荐替代方案
优先使用官方工具,避免自行维护重复代码:
- EF Core场景:直接使用原生
IQueryable<T>的异步方法,无需任何包装 - 内存集合场景:安装
System.Linq.Async包,调用source.ToAsyncEnumerable()即可获得标准异步枚举实现
内容的提问来源于stack exchange,提问作者RoLYroLLs
相关产品推荐
相关产品推荐

