It's a bit tricky to get data from CosmosDb FeedIterator converted into IEnumerable in a simple reusable way without having to write loops and iteration all over the place.
The official Microsoft example which is not as neat as I like it looks like this:
using (FeedIterator setIterator = container.GetItemLinqQueryable<Book>()
.Where(b => b.Title == "War and Peace")
.ToFeedIterator())
{
//Asynchronous query execution
while (setIterator.HasMoreResults)
{
foreach(var item in await setIterator.ReadNextAsync())
{
Console.WriteLine(item.Price);
}
}
}
I'd like to have a reusable oneliner and didn't find one, so I wrote one.
Especially when it's to be used in a .NET API so I wrote an extension method to convert the FeedIterator to IAsyncEnumerable that you can use the
(In C# 8 you can return IAsyncEnumerable from your API but if you need compatibility with netstandard2.0 as I do you can convert the IAsyncEnumerable to a regular IEnumerable)
This is how I solved it:
Extension method:
public static class CosmosDbExtensions
{
/// <summary>
/// Convert a feed iterator to IAsyncEnumerable
/// </summary>
/// <typeparam name="TModel"></typeparam>
/// <param name="setIterator"></param>
/// <returns></returns>
public static async IAsyncEnumerable<TModel> ToAsyncEnumerable<TModel>(this FeedIterator<TModel> setIterator)
{
while (setIterator.HasMoreResults)
foreach (var item in await setIterator.ReadNextAsync())
{
yield return item;
}
}
}
To return IAsyncEnumerable:
public virtual IAsyncEnumerable<TModel> Query()
{
Container container = GetContainer(); // Your code to get container
return container.GetItemLinqQueryable<TModel>().ToFeedIterator().ToAsyncEnumerable();
}
To return IEnumerable:
public virtual async Task<IEnumerable<TModel>> Query()
{
Container container = GetContainer(); // Your code to get container
using (var feedIterator = container.GetItemLinqQueryable<TModel>().ToFeedIterator())
{
return await feedIterator.ToAsyncEnumerable().ToListAsync();
}
}
(More about .ToListAsync() from the System.Linq.Async package in this thread)