IAsyncCursor如何用于mongodb c#驱动程序的迭代?

时间:2015-04-16 17:50:28

标签: c# .net mongodb async-await mongodb-.net-driver

我试图获取服务器中所有数据库的列表,并最终打印出来(即将其名称用作string s)。使用以前版本的c#驱动程序,我可以调用Server.GetDatabases(),但已将其替换为ListDatabasesAsync()

返回值为IAsyncCursor<>,我不知道如何处理它。如何用这样的光标遍历数据库列表(或任何东西)?

2 个答案:

答案 0 :(得分:27)

简答:使用ForEachAsync扩展方法:

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

答案很长:C#中的传统迭代是使用IEnumerableforeach完成的。 foreach是编译器的语法糖。它实际上是对GetEnumeratorusing范围和while循环的调用。但这并不支持异步操作:

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

IAsyncCursor相当于IEnumeratorIEnumerable.GetEnumerator的结果)而IAsyncCursorSource相当于IEnumerable。不同之处在于这些支持async(并且每次迭代都获得批处理,而不仅仅是单个项目)。您不能使用为foreach构建的IEnumerable,但您可以实现整个usingwhile循环内容:

IAsyncCursorSource<int> cursorSource = null;

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

然而,这是很多样板,因此驱动程序为IAsyncCursorForEachAsyncToListAsync添加了扩展方法。

这涵盖了大多数常见用例,但对于其他用户,您仍需要自己实现迭代。

答案 1 :(得分:3)

我个人很喜欢将光标转换为C#8 IAsyncEnumerable,这样您就可以获得使用枚举(主要是LINQ)的所有好处。

使用@ i3arnon的“长答案”,我创建了此扩展方法:

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