【问题标题】:MongoDB c# driver - ForEachAsync vs ToListAsyncMongoDB c# 驱动程序 - ForEachAsync 与 ToListAsync
【发布时间】:2020-11-02 19:29:51
【问题描述】:

我正在使用 MongoDB c# 驱动程序来实现以下目标:对于满足特定条件的所有记录,将记录日期字段之一设置为另一个日期字段的值。 我希望为此使用UpdateAllAsync,但似乎没有方便的方法来做到这一点。 所以现在我想知道使用ForEachAsync 与使用ToListAsync

await this.repository.Find(filter).ForEachAsync(async record =>
{
    await this.repository.UpdateOneAsync(
        Builders<Records>.Filter.Eq(x => x.Id, record.Id),
        Builders<Records>.Update.Set(x => x.Date1, record.Date2));
});

var records = await this.repository.Find(filter).ToListAsync();
foreach (var record in records)
{
    await this.repository.UpdateOneAsync(
        Builders<Records>.Filter.Eq(x => x.Id, record.Id),
        Builders<Records>.Update.Set(x => x.Date1, record.Date2));  
}

第一种方法安全吗?在这种情况下哪种方法更好?

【问题讨论】:

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


    【解决方案1】:

    区别

    ToListAsync() 会将所有数据带入内存,然后对其进行迭代。如果我们谈论的是大量行,这可能会导致长时间使用过多的内存。

    ForEachAsync() 另一方面,将以异步方式一次读取一行,并且不会将所有内容都带入内存。在后台,Async Enumerator 只会在结果集上使用ReadAsync() 来返回下一项。

    两者都将异步运行,这意味着它们不会阻塞主线程。

    为什么ToListAsync

    ForEachAsync 扩展有一个限制。

    检查签名:ForEachAsync(IQueryable, Action&lt;Object&gt;) 它只需要一个Action 委托,这意味着如果您需要任何操作的返回值,则不能使用它。

    解决ForEachAsync 限制的好方法:Unexpected behaviour with Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ForEachAsync<T>()

    【讨论】:

    • ForEachAsync 只接受 Action&lt;Object&gt; 而不是 Func&lt;Task, Object&gt; 也意味着它不应该与异步回调一起使用。
    • 为指出这一点干杯!我根据另一个答案添加了绕过这些问题的解决方法。
    • 感谢您的回答,@athanasios-kataras。在我的示例中,我使用了另一个签名:public static Task ForEachAsync&lt;TDocument&gt;(this IAsyncCursor&lt;TDocument&gt; source, Func&lt;TDocument, Task&gt; processor, CancellationToken cancellationToken = null ),并且根据规范,它返回一个任务,当所有文档都被处理后完成。 (见here)。你知道这与ToListAsync 相比如何吗?
    猜你喜欢
    • 2016-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-04
    • 2018-01-13
    • 2017-12-28
    • 1970-01-01
    相关资源
    最近更新 更多