Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# MongoDB driver transactions on a single MongoDB instance

Tags:

c#

mongodb

I'm using MongoDB 4.0.8 with C# driver 2.8.1 and I'm trying to implement Transactions in my project. I copy-pasted the following code sample:

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

    //Create a session object that is used when leveraging transactions
    var session = client.StartSession();

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

    //Clean up the collection if there is data in there
    products.Database.DropCollection("products");

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

    //Begin transaction
    session.StartTransaction(new TransactionOptions(
                                                    readConcern: ReadConcern.Snapshot,
                                                    writeConcern: WriteConcern.WMajority));

    try
    {
        //Insert the sample data 
        await products.InsertOneAsync(session, TV);
        await products.InsertOneAsync(session, Book);
        await products.InsertOneAsync(session, DogBowl);

        var filter = new FilterDefinitionBuilder<Product>().Empty;
        var results = await products.Find(filter).ToListAsync();

        //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, filter, update); //,options);

        //Made it here without error? Let's commit the transaction
        session.CommitTransaction();

        //Let's print the new results to the console
        Console.WriteLine("Original Prices:\n");
        results = await products.Find<Product>(filter).ToListAsync();
        foreach (Product d in results)
        {
            Console.WriteLine(String.Format("Product Name: {0}\tPrice: {1:0.00}", d.Description, d.Price));
        }
    }
    catch (Exception e)
    {
        Console.WriteLine("Error writing to MongoDB: " + e.Message);
        session.AbortTransaction();
    }
    return true;
}

But in the first Insert command, I'm getting this error:

Command insert failed:
Transaction numbers are only allowed on a replica set member or mongos.

The Documentation says that:

Starting in version 4.0, MongoDB provides the ability to perform multi-document transactions against replica sets.

I don't have replicas in my project, I have only one database instance which is my primary one. If there a solution or a work-around I can use to implement Transactions? I have methods that update more than one collection and I really think it could save me time to use it.

like image 252
Liran Friedman Avatar asked Nov 07 '22 15:11

Liran Friedman


1 Answers

like the documentation says, transactions only work with replica sets. so you need to run your mongodb server as single node replica set. to achieve that, do the following steps...

step 1: stop the mongodb server.

step 2: add the replication setting to your mongod.cfg file. here's my own as an example

storage:
  dbPath: C:\DATA
  directoryPerDB: true
  journal:
    enabled: true

systemLog:
  destination: file
  logAppend: true
  path:  C:\DATA\log\mongod.log

net:
  port: 27017
  bindIp: 127.0.0.1

replication:
   replSetName: MyRepSet

step 3: open up a mongodb shell and issue the following command to initiate the replica set.

rs.initiate()

step 4: restart mongod


on a side-note, if you'd like to write cleaner, more convenient transaction code like the following, check out my library MongoDB.Entities

    using (var TN = new Transaction())
    {
         var author = new Author { Name = "one" };

         TN.Save(author);

         TN.Delete<Book>(book.ID);

         TN.Commit();
    }
like image 175
Dĵ ΝιΓΞΗΛψΚ Avatar answered Nov 14 '22 23:11

Dĵ ΝιΓΞΗΛψΚ