Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

multiple document transaction not working in c# using mongodb 4.08 community server

I need update multiple documents using mongodb transaction, mongodb community server version is 4.08, and mongodb driver for .net is 2.9 beta(also tried 2.8). From debugging, I can see it executed 'session.AbortTransaction();', but data was still inserted.

var client = new MongoClient(_config.GetConnectionString(ProductMongoDBContext.DATABASE_CONNECTION_STRING));
var session = client.StartSession();

try
{
    session.StartTransaction();
    //var database = session.Client.GetDatabase(ProductMongoDBContext.DATABASE_NAME);
    var orders = session.Client.GetDatabase(ProductMongoDBContext.DATABASE_NAME).GetCollection<DALOrder>(ProductMongoDBContext.TABLE_NAME_ORDER);
    var products = session.Client.GetDatabase(ProductMongoDBContext.DATABASE_NAME).GetCollection<DALProduct>(ProductMongoDBContext.TABLE_NAME_PRODUCT);

DateTime dtNow = DateTime.Now.ToUniversalTime();
await orders.InsertOneAsync(new DALOrder
{
    ID = order.ID,
    ProductID = Guid.Parse(order.ProductID),
    Size = order.Size,
    Taste = order.Taste,
    TextOnCake = order.TextOnCake,
    Consignee = order.Consignee,
    ConsigneeAddress = order.ConsigneeAddress,
    ConsigneePhone = order.ConsigneePhone,
    DeliveryTime = order.DeliveryTime.ToUniversalTime(),
    DeliveryWay = order.DeliveryWay,
    OrderDepartment = order.OrderDepartment,
    Remarks = order.Remarks,
    State = OrderState.New.ToString(),
    CreatedTime = dtNow,
    UpdatedTime = dtNow
});

// After order created, decrease product inventory by one
var productInfo = products.Find<DALProduct>(p => p.ID.ToString().Equals(order.ProductID)).FirstOrDefault();
productInfo.Inventory -= 1;
await products.ReplaceOneAsync<DALProduct>(p => p.ID.ToString().Equals(order.ProductID), productInfo);

session.CommitTransaction();

return true;
}
catch (Exception e)
{
    session.AbortTransaction();
    order.Message = e.Message;
}

Expect inserted order data can be rollback, actual result is the data has been inserted into db.

BTW, the error occurs at

    var productInfo = products.Find<DALProduct>(p => p.ID.ToString().Equals(order.ProductID)).FirstOrDefault();
I define ID as GUID in model like below
    [BsonId]
    public Guid ID { get; set; }

it will throw exception like "{document}{_id}.ToString() is not supported." How to avoid this

like image 890
Yu Taylor Avatar asked Dec 30 '25 18:12

Yu Taylor


1 Answers

I can see it executed 'session.AbortTransaction();', but data was still inserted.

The reason why the operations are executed (i.e. data was still inserted after abort), because the operations are not contained within a transactional session.

All of the CRUD operations should have an overloaded methods that specifies IClientSessionHandle as its first argument. For example:

Task InsertOneAsync(IClientSessionHandle session, TDocument document, InsertOneOptions options = null, CancellationToken cancellationToken = default(CancellationToken));

See: InsertOneAsync and ReplaceOneAsync in MongoDB .NET/C# driver v2.8.1.

To ensure the operations are contained within the transactional session, pass the session as an argument to the CRUD operations. Any operations that don't have the session object, will be executed outside of the session.

like image 176
Wan Bachtiar Avatar answered Jan 01 '26 09:01

Wan Bachtiar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!