如何使用C#中的Task在Mongo中包装大容量upsert

时间:2018-07-02 03:31:15

标签: c# mongodb asynchronous

我有一些模特

public partial class Option
{
  [BsonId]
  public int Id { get; set; }
  public Quote Quote { get; set; }
  public Contract Contract { get; set; }
}

可以批量写入的方法

public Task SaveOptions(List<Option> contracts)
{
  var context = new MongoContext();
  var processes = new List<Task<UpdateResult>>();
  var collection = context.Storage.GetCollection<Option>("options");

  contracts.ForEach(contract =>
  {
    var item = Builders<Option>.Update.Set(o => o, contract);
    var options = new UpdateOptions { IsUpsert = true };

    processes.Add(collection.UpdateOneAsync(o => o.Id == contract.Id, item, options));
  });

  return Task.WhenAll(processes);
}

调用上述方法

Task.WhenAll(service.SaveOptions(contracts)) // also tried without Task.WhenAll

由于某种原因,它不会在Mongo DB中创建任何记录

更新

试图以这种方式重写批量写入,仍然没有变化。

public Task SaveOptions(List<Option> contracts)
{
  var context = new MongoContext();
  var records = new List<UpdateOneModel<Option>>();
  var collection = context.Storage.GetCollection<Option>("options");

  contracts.ForEach(contract =>
  {
    var record = new UpdateOneModel<Option>(
      Builders<Option>.Filter.Where(o => o.Id == contract.Id),
      Builders<Option>.Update.Set(o => o, contract))
    {
      IsUpsert = true
    };

    records.Add(record);
  });

  return collection.BulkWriteAsync(records);
}

1 个答案:

答案 0 :(得分:1)

我认为您想使用ReplaceOneAsync

processes.Add(collection.ReplaceOneAsync(o => o.Id == contract.Id, contract, options));

此处使用UpdateOneAsync的问题在于,您应该指定一个 field 进行更新,而o => o则不这样做。由于要替换整个对象,因此需要使用ReplaceOneAsync

**请注意,您也可以通过创建BulkWriteAsync而不是ReplaceOneModel来使用UpdateOneModel