Bel*_*way 4 entity-framework-core asp.net-core-webapi iasyncenumerable
我目前有一个 Web API
FromSqlRaw(...).ToListAsync()在存储库中使用获取一行数据Ok(data.ToArray())像Task<ActionResult<IEnumerable<MyClass>>>通过控制器一样返回此数据。现在我想知道我是否应该或可以使用 IAsyncEnumerable 作为返回类型。这个想法是在存储库和控制器中使用它。然而,在这个(现在已经破旧的)线程中,它声明不应该使用它。这里建议的解决方案类似于:
FromSqlRaw(...).AsNoTracking().AsAsyncEnumerable()
Run Code Online (Sandbox Code Playgroud)
至于控制器,我希望将响应包装起来ActionResult以显式设置返回码。然而,这目前似乎并没有工作。
我应该只为存储库应用解决方案并将结果作为列表在我的控制器中使用还是保持原样?
该IAsyncEnumerable给你的接口基于拉的异步数据检索。换句话说,此 API 表示一个迭代器,在该迭代器中异步获取下一项。
这意味着您将分几轮接收数据,并且每轮都以异步方式接收。
之前IAsyncEnumerable你可以使用IEnumerable<Task<T>>,它代表一堆具有返回类型的异步操作T。
而Task<IEnumerable<T>>表示具有返回类型的单个异步操作IEnumerable<T>。
让我们将这些知识应用到 WebAPI 中:
Task<ActionResult<T>>和 之间没有区别ActionResult<T>。从用户的角度来看,这是一个实现细节。这意味着 API 的使用者无法利用IAsyncEnumerable它作为操作结果类型公开的优势。
在 .net 6 中,使用System.Text.Json时, MVC 的IAsyncEnumerable处理发生了变化:
MVC 不再缓冲 IAsyncEnumerable 实例。相反,MVC 依赖于 System.Text.Json 为这些类型添加的支持。
这意味着控制器将立即开始发送输出,并且客户端可以在收到响应块时开始处理它。
这是一个借助新的最小 API的示例:
端点绑定:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
// this endpoint return IAsyncEnumerable<TestData>
app.MapGet("/asyncEnumerable/{count}", (int count) => GetLotsOfDataAsyncEnumerable(count));
// and this one returns Task<IEnumerable<TestData>>
app.MapGet("/{count}", async (int count) => await GetLotsOfDataAsync(count));
app.Run();
Run Code Online (Sandbox Code Playgroud)
控制器方法:
async Task<IEnumerable<TestData>> GetLotsOfDataAsync(int count)
{
var list = new List<TestData>();
for (int i = 0; i < count; i++)
{
await Task.Delay(10);
list.Add(new TestData($"{i}"));
}
return list;
}
async IAsyncEnumerable<TestData> GetLotsOfDataAsyncEnumerable(int count)
{
for (int i = 0; i < count; i++)
{
await Task.Delay(10);
yield return new TestData($"{i}");
}
}
class TestData
{
public string Field { get; }
public TestData(string field)
{
Field = field;
}
}
Run Code Online (Sandbox Code Playgroud)
计数路径变量允许控制我们想要在一次调用中检索多少数据。
我在 Windows 机器上使用curl命令对其进行了测试(这是解释如何使用curl测量性能的答案),100个条目的结果:
/100 /asyncEnumerable/100
time_namelookup: 0.000045s 0.000034s
time_connect: 0.000570s 0.000390s
time_appconnect: 0.000000s 0.000000s
time_pretransfer: 0.000648s 0.000435s
time_redirect: 0.000000s 0.000000s
time_starttransfer: 1.833341s 0.014880s
---------------------
time_total: 1.833411s 1.673477s
Run Code Online (Sandbox Code Playgroud)
这里重要的是要看到time_starttransfer,来自curl手册页
从开始到第一个字节即将传输所花费的时间(以秒为单位)。这包括 time_pretransfer 以及服务器计算结果所需的时间。
正如您所看到的/asyncEnumerable端点立即开始响应,当然,此类端点的客户端必须了解此类行为才能充分利用它。
| 归档时间: |
|
| 查看次数: |
299 次 |
| 最近记录: |