【问题标题】:C# MongoDB driver transactions on a single MongoDB instance单个 MongoDB 实例上的 C# MongoDB 驱动程序事务
【发布时间】:2019-07-28 21:41:54
【问题描述】:

我正在使用带有 C# 驱动程序 2.8.1 的 MongoDB 4.0.8,并且我正在尝试在我的项目中实现 Transactions。 我复制粘贴了以下代码示例:

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

但是在第一个 Insert 命令中,我收到了这个错误:

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

Documentation 说:

从 4.0 版开始,MongoDB 提供了针对副本集执行多文档事务的能力。

我的项目中没有副本,我只有一个数据库实例,这是我的主要实例。如果有解决方案或变通方法我可以用来实现Transactions?我有更新多个集合的方法,我真的认为它可以节省我使用它的时间。

【问题讨论】:

    标签: c# mongodb


    【解决方案1】:

    如文档所述,事务仅适用于副本集。因此您需要将 mongodb 服务器作为单节点副本集运行。为此,请执行以下步骤...

    第 1 步: 停止 mongodb 服务器。

    第 2 步:replication 设置添加到您的 mongod.cfg 文件中。这是我自己的例子

    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
    

    第 3 步: 打开一个 mongodb shell 并发出以下命令来启动副本集。

    rs.initiate()
    

    第四步:重启mongod


    附带说明,如果您想编写更简洁、更方便的事务代码,如下所示,请查看我的库 MongoDB.Entities

        using (var TN = new Transaction())
        {
             var author = new Author { Name = "one" };
    
             TN.Save(author);
    
             TN.Delete<Book>(book.ID);
    
             TN.Commit();
        }
    

    【讨论】:

    • 参见评论 #2 here:您可以使用一个节点启动副本集以用于开发目的。启动一个 mongod --replSet 然后在 mongo shell 中执行 rs.initiate() 。请注意,这不是生产环境的推荐设置。
    • @LiranFriedman 我假设您使用的是mongod.cfg 文件。本质上是一样的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-13
    • 1970-01-01
    • 2016-09-20
    • 1970-01-01
    • 2012-03-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多