之前的方法返回Task<IEnumerable<T>>,在.NET Core 3.0中可以使用IAsyncEnumerable<T>,本文介绍一下.NET Core 3.0 中使用IAsyncEnumerable<T>方法及示例代码。

1、IAsyncEnumerable<T>和yield return的使用

IAsyncEnumerable<T>是在.NET Core 3(.NET Standard 2.1)中引入的。它公开了具有MoveNextAsync()可以等待的方法的枚举器。这意味着生产者可以在产生结果之间进行异步调用。

public async IAsyncEnumerable<Product> GetAllProducts()
{
    Container container = cosmosClient.GetContainer(DatabaseId, ContainerId);
    var iterator = container.GetItemQueryIterator<Product>("SELECT * FROM c");
    while (iterator.HasMoreResults)
    {
        foreach (var product in await iterator.ReadNextAsync())
        {
            yield return product;
        }
    }
}

使用await foreach()C#8中可用的新语法获取结果:

await foreach (var product in productsRepository.GetAllProducts())
{
Console.WriteLine(product);
}

2、ASP.NET Core中使用IAsyncEnumerable<T>

从.NET Core 3开始,ASP.NET能够IAsyncEnumerable<T>从API控制器操作中返回。这意味着我们可以直接返回方法的结果-有效地将数据从数据库流式传输到HTTP响应。

[HttpGet]
public IAsyncEnumerable<Product> Get()
=> productsRepository.GetAllProducts();

3、FeedIterator<T>扩展方法使用IAsyncEnumerable<T>

通过在FeedIterator<T>上扩展方法实现Azure Cosmos DB 3.0 SDK利用IAsyncEnumerable<T>查询数据。

public static class FeedIteratorExtensions
{
public static async IAsyncEnumerable<T> ToAsyncEnumerable<T>(this FeedIterator<T> iterator)
{
while (iterator.HasMoreResults)
{
foreach(var item in await iterator.ReadNextAsync())
{
yield return item;
}
}
}
}

简洁的方式处理查询结果:

var products = container
.GetItemQueryIterator<Product>("SELECT * FROM c")
.ToAsyncEnumerable();
await foreach (var product in products)
{
Console.WriteLine(product.Name);
}