You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 21:10:46