ASP.NET 6 - IAsyncEnumerable 的异步序列化 class 属性

ASP.NET 6 - Asynchronous serialization of IAsyncEnumerable class property

ASP.NET Core 现在支持从控制器操作一直到响应 JSON 格式化程序的异步流。从操作返回 IAsyncEnumerable 不再在发送之前在内存中缓冲响应内容。这有助于在返回可异步枚举的大型数据集时减少内存使用量。

由于DbSet实现了IAsyncEnumerable,完全支持以下示例:

[ApiController]
public class Controller : ControllerBase
{
    private readonly DbContext _context;

    public Controller(DbContext context) => _context = context;

    [HttpGet]
    public IAsyncEnumerable<AspNetUser> GetData()
    {
        return _context.AspNetUsers.AsAsyncEnumerable();
    }
}

看似只有在返回数据源本身时才能使用此功能,但是当数据源被包装时,以便可以发送额外的元数据,流式传输是不可能的。

基本API结果:

public class DataSourceResult<T>
{
    public IEnumerable<T> Data { get; set; }
    public int PageIndex { get; set; }
    public int PageSize { get; set; }
    public int TotalCount { get; set; }
}

由于我的许多应用程序都是 运行 在低内存环境中运行的,因此我正在寻找一些关于如何在这种情况下使用异步流的建议,在这种情况下,数据本身是间接返回的。

您需要做的就是将 DataSourceResult<T> class 更改为 Data 属性 类型的 IAsyncEnumerable<T>System.Text.Json 序列化程序识别类型并将其流式传输到客户端。所以:

public class DataSourceResult<T>
{
    public IAsyncEnumerable<T> Data { get; set; }
    public int PageIndex { get; set; }
    public int PageSize { get; set; }
    public int TotalCount { get; set; }
}

你的动作应该是这样的:

public DataSourceResult<AspNetUser> GetData()
{
    return new DataSourceResult<AspNetUser>
    {
        Data = _context.AspNetUsers.AsAsyncEnumerable(),
        PageIndex = 1,
        PageSize = 10,
        TotalCount = 12345
    };
}