How to wrap bulk upsert in Mongo with Task in C#


How to wrap bulk upsert in Mongo with Task in C#



I have some model


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



Method that does bulk write


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);
}



Call for the method above


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



For some reason, it doesn't create any record in Mongo DB



Update



Tried to rewrite bulk write this way, still no changes.


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);
}





Hint: You don't want UpdateOne, you want ReplaceOne :)
– john
Jul 2 at 4:22


UpdateOne


ReplaceOne





@john it works, add this as an answer and I will accept it
– Anonymous
Jul 2 at 4:50





even though, I thought that update and replace do the same thing, but update is more flexible because it allows to change structure of the record on update
– Anonymous
Jul 2 at 4:50




1 Answer
1



I think you want to use ReplaceOneAsync:


ReplaceOneAsync


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



The problem with using UpdateOneAsync here is that you're supposed to specify a field to update, and o => o doesn't do that. Since you want to replace the entire object, you need to use ReplaceOneAsync.


UpdateOneAsync


o => o


ReplaceOneAsync



** Note that you can also do this with BulkWriteAsync by creating a ReplaceOneModel instead of an UpdateOneModel.


BulkWriteAsync


ReplaceOneModel


UpdateOneModel






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

api-platform.com Unable to generate an IRI for the item of type

How to set up datasource with Spring for HikariCP?

Display dokan vendor name on Woocommerce single product pages