如何 运行 对游标的最终迭代进行编码
How to run code on final iteration on a cursor
我有一个存储库函数 GetDocs(),returns 一个 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++;
});
}
像这样的事情怎么样?基本上,循环会将之前的文档存储在内存中,并在下一次迭代中处理它。这样,一旦它退出循环,它就会得到 "last doc" 并可以将其标记为处理器。
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);
}
}
}
我有一个存储库函数 GetDocs(),returns 一个 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++;
});
}
像这样的事情怎么样?基本上,循环会将之前的文档存储在内存中,并在下一次迭代中处理它。这样,一旦它退出循环,它就会得到 "last doc" 并可以将其标记为处理器。
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);
}
}
}