首页 > 解决方案 > 如何使用 .net 驱动程序 2.7.3 同时将新文档插入到 MongoDB 4 中的集合中

问题描述

我正在使用 MongoDB 4 和 MongoDB .net 驱动程序 2.7.3。我想同时在集合中插入一个新文档,以便集合中应该只有一个文档。文档插入集合后(即设置sequenceValue为1),我们只需要更新文档(即将sequenceValue加1),而不需要再插入新的文档。

在这个名为“countersCollection”的集合中,新文档的结构是一个 Counter 类,如:

    public class Counter
    {
        [BsonId]
        public ObjectId _id { get; set; }
        public string name { get; set; }
        public long sequenceValue {get;set;}
        public DateTime date {get;set;}
    }

我的代码是这样的:

    Counter c = await this.countersCollection.AsQueryable().FirstOrDefaultAsync(x => x.name == counterName);                
    DateTime utcNow = DateTime.UtcNow;                                                                            
    if (c == null) // empty document
    {
        var options = new FindOneAndUpdateOptions<Counter, Counter>() {ReturnDocument = ReturnDocument.After, IsUpsert = true };            
        var filter = new FilterDefinitionBuilder<Counter>().Where(x => x.name == counterName);
        var update = new UpdateDefinitionBuilder<Counter>().Set(x => x.sequenceValue, 1).Set(x => x.date, utcNow);                                        
        seq = await this.countersCollection.FindOneAndUpdateAsync<Counter>(filter, update, options);                    
    }

上面的代码在非并发环境中运行良好,但不能同时运行良好。如果多个线程同时调用上述代码,可能会在 countersCollection 中创建多个计数器文档。

有没有办法让它同时工作。

谢谢你。

标签: c#.netmongodbconcurrency

解决方案


您可以使用乐观并发方法来处理它

算法可以是:

  1. Counter发现name == counterName
  2. 建立你的过滤器 var filter = new FilterDefinitionBuilder<Counter>().Where(x => x.name == counterName && x.sequenceValue == c.sequenceValue );
  3. 尝试查找并更新,如果结果是null重试

推荐阅读