Async MongoDB中的并发更改(C#)

时间:2016-09-07 18:44:04

标签: c# mongodb

假设我有一个简单的对象:

class A
{
    int _id;
    int V1;
    int V2;
}

和一堆MongoDB表:

现在,我有两个异步更新操作定义如下:

void UpdateV1(int id, int V)
{    
    var F = Builders<A>.Filter.Eq(_ => _._id, Id);
    var U = Builders<A>.Update.Set(_ => _.V1, V);
    Mongo.Driver.UpdateOneAsync(F, U);
}

void UpdateV2(int id, int V)
{    
    var F = Builders<A>.Filter.Eq(_ => _._id, Id);
    var U = Builders<A>.Update.Set(_ => _.V2, V);
    Mongo.Driver.UpdateOneAsync(F, U);
}

如果我运行以下命令:

UpdateV1(1, 10);

UpdateV2(1, 20);

在不同的线程上,但大致在同一时间,发生了什么?

我能得到:

  • 只有V1或V2发生变化的记录?
  • V1和V2都已更改的记录?

我之所以这样问是因为我们有一个非常奇怪的错误,看起来第一个选项就是发生了什么,但预期结果显然是最后一个。

当我们进行阻止呼叫时,这些问题开始消失,但也可能是副作用。

这是使用C#驱动程序,所有最新版本。

1 个答案:

答案 0 :(得分:0)

我认为这不是您的查询问题,因为mongodb保证原子性和并发控制可以查看此link以获取更多信息。

你的问题来自我怀疑的任务安排方式。 看看这个例子,如果你没有等待Parallel.Invoke中的结果,你的查询将不会被执行,因为进程将在执行任务之前退出。因此,如果添加Console.ReadLine(),您的流程将被阻止,从而允许mongo运行任务

namespace ConsoleApplication1
{
    class Program
    {
       static MongoClient mongoClient = new MongoClient();
        static IMongoDatabase databaseBase = mongoClient.GetDatabase("dbTest", null);
        static IMongoCollection<A> collection = databaseBase.GetCollection<A>("tests", null);
        static void Main(string[] args)
        {

            var a = new A
            {
                _id = 1,
                V1 = 0,
                V2 = 0
            };

            Parallel.Invoke( ()=> { var res=UpdateV1(1, 10).Result; },  ()=> { var res =  UpdateV2(1, 20).Result; });
            //Console.ReadLine(); 




        }
        static async  Task<long> UpdateV1(int id, int V)
        {
            var F = Builders<A>.Filter.Eq(a => a._id, id);
            var U = Builders<A>.Update.Set(a => a.V1, V);
            var result = await collection.UpdateOneAsync(F, U);
            return result.ModifiedCount;  
        }

        static async Task<long> UpdateV2(int id, int V)
        {
            var F = Builders<A>.Filter.Eq(_ => _._id, id);
            var U = Builders<A>.Update.Set(_ => _.V2, V);
            var result = await collection.UpdateOneAsync(F, U);
            return result.ModifiedCount;
        }


    }
    class A
    {
       public  int _id;
       public   int V1;
       public  int V2;
    }
}

您可能只需将UpdateOneAsync替换为UpdateOne,看看会发生什么?