我有一个存储库函数,GetDocs(),它返回一个MongoDB游标。
在我调用GetDocs的地方,我迭代光标,在每五次迭代中,我调用SetLastId()。
问题:如何确定何时处理光标的最后一个元素,以便在退出循环之前调用SetLastId()?
public async Task GetDocs(string id, Func<Model, Task> processor)
{
var filter = Builders<Model>.Filter;
var sort = Builders<Model>.Sort;
using (var cursor = await Coll.Find(filter.Eq(f => f.id, id)).ToCursorAsync())
{
foreach (var doc in cursor.Current)
{
await processor(doc);
}
}
}
.
using (OdbcConnection conn = new OdbcConnection(context.connectionString))
{
conn.Open();
int counter = 0;
await repo.GetDocs(context.Id, async (doc) =>
{
if (counter % 5 == 0)
{
var success = await SetLastId(doc.Id);
}
counter++;
});
}
这样的事情怎么样?基本上,循环将先前的文档存储在内存中并在下一次迭代中处理它。这样,一旦它退出循环,就会有“最后的文档”,并且可以将其标记为处理器。
public async Task GetDocs(string id, Func<Model, bool, Task> processor)
{
var filter = Builders<Model>.Filter;
var sort = Builders<Model>.Sort;
using (var cursor = await Coll.Find(filter.Eq(f => f.id, id)).ToCursorAsync())
{
Model previousDoc = null;
foreach (var doc in cursor.Current)
{
if (previousDoc != null)
{
await processor(previousDoc, false);
}
previousDoc = doc;
}
if (previousDoc != null)
{
await processor(previousDoc, true);
}
}
}
你也可以将它包装成一个可重用的方法,适用于任何IEnumerable(我在这里使用过ValueTuples,但如果你不能使用它们,你可以自己创建类型):
public static IEnumerable<(T Model, bool IsLast)> Map<T>(IEnumerable<T> items)
{
T prevModel = default(T);
bool isFirst = true;
foreach (var model in items)
{
if (!isFirst)
{
yield return (prevModel, false);
}
else
{
isFirst = false;
}
prevModel = model;
}
if (!isFirst)
{
yield return (prevModel, true);
}
}
public async Task GetDocs(string id, Func<Model, bool, Task> processor)
{
var filter = Builders<Model>.Filter;
var sort = Builders<Model>.Sort;
using (var cursor = await Coll.Find(filter.Eq(f => f.id, id)).ToCursorAsync())
{
foreach (var docWrapper in Map(cursor.Current))
{
await processor(docWrapper.Model, docWrapper.IsLast);
}
}
}