如何在游标上的最后一次迭代上运行代码

问题描述 投票:0回答:1

我有一个存储库函数,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++;
         });
    }
c# mongodb mongodb-.net-driver database-cursor
1个回答
1
投票

这样的事情怎么样?基本上,循环将先前的文档存储在内存中并在下一次迭代中处理它。这样,一旦它退出循环,就会有“最后的文档”,并且可以将其标记为处理器。

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);
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.