Can I use dispose patten to ensure rollback/AbortTransaction in a session transaction use c# dirver

I see the example form mongodb offical:

    private static async Task<bool> UpdateProductsAsync()
            // Create client connection to our MongoDB database
            var client = new MongoClient(MongoDBConnectionString);

            // Create the collection object that represents the "products" collection
            var database = client.GetDatabase("MongoDBStore");
            var products = database.GetCollection<Product>("products");

            // Clean up the collection if there is data in there
            await database.DropCollectionAsync("products");

            // collections can't be created inside a transaction so create it first
            await database.CreateCollectionAsync("products"); 

            // Create a session object that is used when leveraging transactions
            using (var session = await client.StartSessionAsync())
                // Begin transaction

                    // Create some sample data
                    var tv = new Product { Description = "Television", 
                                    SKU = 4001, 
                                    Price = 2000 };
                    var book = new Product { Description = "A funny book", 
                                    SKU = 43221, 
                                    Price = 19.99 };
                    var dogBowl = new Product { Description = "Bowl for Fido", 
                                    SKU = 123, 
                                    Price = 40.00 };

                    // Insert the sample data 
                    await products.InsertOneAsync(session, tv);
                    await products.InsertOneAsync(session, book);
                    await products.InsertOneAsync(session, dogBowl);

                    var resultsBeforeUpdates = await products
                                    .Find<Product>(session, Builders<Product>.Filter.Empty)
                    Console.WriteLine("Original Prices:\n");
                    foreach (Product d in resultsBeforeUpdates)
                                    String.Format("Product Name: {0}\tPrice: {1:0.00}", 
                                        d.Description, d.Price)

                    // Increase all the prices by 10% for all products
                    var update = new UpdateDefinitionBuilder<Product>()
                            .Mul<Double>(r => r.Price, 1.1);
                    await products.UpdateManyAsync(session, 
                            update); //,options);

                    // Made it here without error? Let's commit the transaction
                    await session.CommitTransactionAsync();
                catch (Exception e)
                    Console.WriteLine("Error writing to MongoDB: " + e.Message);
                    await session.AbortTransactionAsync();
                    return false;

                // Let's print the new results to the console
                Console.WriteLine("\n\nNew Prices (10% increase):\n");
                var resultsAfterCommit = await products
                        .Find<Product>(session, Builders<Product>.Filter.Empty)
                foreach (Product d in resultsAfterCommit)
                        String.Format("Product Name: {0}\tPrice: {1:0.00}", 
                                                    d.Description, d.Price)

                return true;

It use a very old patten try catch{ rollback }. Currently in dotnet always use a using/dispose patten to ensure
rollback. for example the DbTransaction class:

using (transaction = ....)

The above code not call the rollback directly but it’s ok because dispose method will try call rollback method.
So My question is in c# driver Can i only use using/dispose and no call AbortTransactionAsync in transaction case?

Hi, @Minjie.ZHOU_N_A ,

Welcome to the MongoDB Community Forums. Yes, you can use the dispose pattern with the session. See an example in our docs.

Note that Dispose is a blocking operation and if you want to be fully async, you must explicitly call AbortTransactionAsync noted in the linked example. .NET 8 introduces DisposeAsync, which we will be implemented in a future version of the driver but is not present yet.


1 Like

Thank you very much James.