How is an IAsyncCursor used for iteration with the mongodb c# driver?

Short answer: use the ForEachAsync extension method:

var cursor = await client.ListDatabasesAsync();
await cursor.ForEachAsync(db => Console.WriteLine(db["name"]));

Long answer: Traditional iteration in C# is done with IEnumerable and foreach. foreach is the compiler's syntactic sugar. It's actually a call to GetEnumerator, a using scope and a while loop. But that doesn't support asynchronous operations:

using (var enumerator = enumerable.GetEnumerator())
{
    while (enumerator.MoveNext())
    {
        var current = enumerator.Current;
        // use current.
    }
}

IAsyncCursor is equivalent to IEnumerator (the result of IEnumerable.GetEnumerator) while IAsyncCursorSource is toIEnumerable. The difference is that these support async (and get a batch each iteration and not just a single item). You can't use foreach as it's built for IEnumerable but you can implement the whole using, while loop thing:

IAsyncCursorSource<int> cursorSource = null;

using (var asyncCursor = await cursorSource.ToCursorAsync())
{
    while (await asyncCursor.MoveNextAsync())
    {
        foreach (var current in asyncCursor.Current)
        {
            // use current
        }
    }
}

However that's a lot of boilerplate so the driver adds extension methods for IAsyncCursor like ForEachAsync, ToListAsync and so forth.

That covers most common use cases but for others you do still need to implement the iteration yourself.


I personally like to convert the cursor into a C# 8 IAsyncEnumerable, that way you get all the benefits of working with enumerables (LINQ mainly).

Using @i3arnon's "long answer" I created this extension method:

public static async IAsyncEnumerable<T> ToAsyncEnumerable<T>(this IAsyncCursor<T> asyncCursor)
{
    while (await asyncCursor.MoveNextAsync())
    {
        foreach (var current in asyncCursor.Current)
        {
            yield return current;
        }
    }
}