I encountered an interesting behavior while exploring IAsyncEnumerable in an ASP.NET Web API project. Consider the following code samples:
// Code Sample 1
[HttpGet]
public async IAsyncEnumerable<int> GetAsync()
{
for (int i = 0; i < 10; i++)
{
await Task.Delay(1000);
yield return i;
}
}
// Code Sample 2
[HttpGet]
public async IAsyncEnumerable<string> GetAsync()
{
for (int i = 0; i < 10; i++)
{
await Task.Delay(1000);
yield return i.ToString();
}
}
Run Code Online (Sandbox Code Playgroud)
Sample 1 (int array) returns {} as …
我有三个返回IAsyncEnumerable的控制器方法WeatherForecast。第一个 #1 使用SqlConnection读者并产生结果async。第二个#2 使用具有使用扩展能力的 EF Core AsAsyncEnumerable。第三个 #3 使用 EF Core 和ToListAsync方法。
我认为 #1 和 #2 的缺点是,例如,如果我在 while 或 for every 内部执行一些耗时的操作,那么数据库连接将一直打开到最后。在场景 #3 中,我可以使用关闭的连接迭代列表并执行其他操作。
但是,我不知道IAsyncEnumerable对于数据库查询是否有意义。是否存在内存和性能问题?如果我用于IAsyncEnumerable从 API 返回 HTTP 请求,那么一旦返回响应,它就不在内存中,我可以返回下一个响应,依此类推。但是数据库呢?如果我选择所有行(使用IAsyncEnumerable或ToListAsync),整个表在哪里?
也许这不是 StackOverflow 的问题,我在这里遗漏了一些重要的东西。
#1
[HttpGet("db", Name = "GetWeatherForecastAsyncEnumerableDatabase")]
public async IAsyncEnumerable<WeatherForecast> GetAsyncEnumerableDatabase()
{
var connectionString = "";
await using var connection = new SqlConnection(connectionString);
string sql = "SELECT * FROM [dbo].[Table]";
await …Run Code Online (Sandbox Code Playgroud) 我正在使用 EF Core 3.1.1(dotnet core 3.1.1)。我想返回大量的 Car 实体。不幸的是,我收到以下错误消息:
'AsyncEnumerableReader' reached the configured maximum size of the buffer when enumerating a value of type 'Microsoft.EntityFrameworkCore.Internal.InternalDbSet`...
Run Code Online (Sandbox Code Playgroud)
我知道还有另一个关于相同错误的已回答问题。但我没有做显式的异步操作。
[HttpGet]
[ProducesResponseType(200, Type = typeof(Car[]))]
public IActionResult Index()
{
return Ok(_carsDataModelContext.Cars.AsEnumerable());
}
Run Code Online (Sandbox Code Playgroud)
_carDataModelContext.Car 只是一个简单的实体,将一对一映射到数据库中的表。 public virtual DbSet<Car> Cars { get; set; }
原来我回来Ok(_carsDataModelContext.Cars.AsQueryable())是因为我们需要支持OData。但为了确保不是 OData 把事情搞砸了,我尝试返回 AsEnumerable,并从方法中删除“[EnableQuery]”属性。但这仍然以相同的错误结束。
解决这个问题的唯一方法是,如果我回来 Ok(_carsDataModelContext.Cars.ToList())