ASP.NET 核心 API 传送流而不是大 JSONArray 的端点

ASP.NET Core API Endpoint which delivers a Stream instead of big JSONArray

我有一个很大的对象列表,需要从客户端快速接收。目前大约需要 2-4 秒。我现在尝试使用流来发送块(例如每个 100 个对象)我知道 GRPC 可以使用流但是在 ASP.NET 核心中,我该如何实现呢?正常的 ASP.NET 具有 PushStreamContent,这在 Core 中不可用。有什么解决办法吗?我真的在网上找不到合适的。

那么我的控制器目前的样子:

 [HttpGet]
 public async Task<ActionResult<IEnumerable<Price>>> GetPrices()
 {
     return await _context.Prices.ToListAsync();
 }

此列表目前包含大约 18700 个项目,但这个数字会随着时间的推移而增加。

根据您的示例,我猜您正在使用 EF Core。

如果您查看 Efficient Querying - Buffering and streaming,他们建议使用 AsEnumerable 来流式传输数据,而不是 ToList,这实际上是在(在您的情况下)之前将所有数据加载到内存中返回给客户。异步版本是 AsAsyncEnumerable.

因此您应该能够简单地将您的控制器操作更改为:

[HttpGet]
public async Task<ActionResult<IEnumerable<Price>>> GetPrices()
{
    return await _context.Prices.AsAsyncEnumerable();
}

请注意,流式传输而不是 buffering/loading 进入内存并不意味着在所有情况下都会提高性能,但是对于大型数据集,您很有可能会看到更好的性能。

is it a code smell / bad practice to send such big JSON data?

不一定。如果您确实需要整个数据集 client-side,那么这可能是最有效的方法。但是,如果您的数据集很大,您应该预料到下载需要一些时间。如果您的下载速度是 5 MB/s 并且您的数据是 Price 10 MB,那么如果没有更好的连接,您的下载速度永远不会超过 2 秒。即使您使用来自后端的流。

另一种方法(如果适合您的需要)是引入分页。这样你就可以检索例如一次 50 个项目,而不是所有项目,然后翻阅它。但是从您的客户端使用分页是否有意义取决于您。