我正在尝试获取我的服务器中所有数据库的列表,并最终将它们打印出来(即使用它们的名称作为string)。使用以前版本的c#驱动程序,我可以调用Server.GetDatabases(),但它已被ListDatabasesAsync()所取代。
返回值是一个IAsyncCursor<>,我不知道如何处理它。如何使用这样的游标遍历数据库列表(或任何内容)?
发布于 2015-04-17 02:31:45
简短回答:使用ForEachAsync扩展方法:
var cursor = await client.ListDatabasesAsync();
await cursor.ForEachAsync(db => Console.WriteLine(db["name"]));长答案:在C#中的传统迭代是使用IEnumerable和foreach完成的。foreach是编译器的语法糖。它实际上是一个对GetEnumerator的调用,一个using作用域和一个while循环。但这不支持异步操作:
using (var enumerator = enumerable.GetEnumerator())
{
while (enumerator.MoveNext())
{
var current = enumerator.Current;
// use current.
}
}IAsyncCursor等同于IEnumerator (IEnumerable.GetEnumerator的结果),而IAsyncCursorSource等同于IEnumerable。不同之处在于,它们支持async (并在每次迭代中获得批处理,而不仅仅是单个项)。你不能使用foreach,因为它是为IEnumerable构建的,但是你可以实现整个using,while循环:
IAsyncCursorSource<int> cursorSource = null;
using (var asyncCursor = await cursorSource.ToCursorAsync())
{
while (await asyncCursor.MoveNextAsync())
{
foreach (var current in asyncCursor.Current)
{
// use current
}
}
}然而,这是大量的样板文件,因此驱动程序为IAsyncCursor添加了ForEachAsync、ToListAsync等扩展方法。
这涵盖了大多数常见用例,但对于其他用例,您仍然需要自己实现迭代。
发布于 2020-06-21 07:24:32
我个人喜欢将光标转换为C# 8 IAsyncEnumerable,这样您就可以获得使用可枚举项(主要是LINQ)的所有好处。
使用@i3arnon的"long answer“我创建了这个扩展方法:
public static async IAsyncEnumerable<T> ToAsyncEnumerable<T>(this IAsyncCursor<T> asyncCursor)
{
while (await asyncCursor.MoveNextAsync())
{
foreach (var current in asyncCursor.Current)
{
yield return current;
}
}
}发布于 2021-09-02 16:21:39
多亏了C# 9中对GetAsyncEnumerator的扩展方法的支持和foreach的鸭式实现,现在可以使用以下扩展方法直接迭代游标:
public static class MongoDbCursorExtensions
{
public static IAsyncCursor<T> GetAsyncEnumerator<T>(this IAsyncCursor<T> cursor) => cursor;
}用法:
var cursor = await collection.Find(filter).ToCursorAsync();
await foreach (var batch in cursor) // extension method implicitly called here
{
foreach (var item in batch)
{
// ...
}
}https://stackoverflow.com/questions/29682371
复制相似问题