Search code examples
mongodbmongodb-.net-driver

How to handle multithreading MongoDb updates from .net classes?


MongoDb, c# driver: Two threads are taking the same single document from MongoDb, changing its state and updating it back to database. I want every thread to detect if any changes were done by other thread between moments of reading and updating this document. If such changes are done by other thread, I do not want current thread to override them and I want to log this information. Please let me know possible solutions for that. I know there is MongoCollection<T>.Update and MongoCollection<T>.FindAndModify methods, where I can define query based on information taken from Db, but I do not see any ways to detect if the document was actually found and updated or not, there is no information like number of records updated returned.


Solution

  • From what I understand, you want optimistic locking.

    A straightforward way to implement optimistic locking is to version your documents and increase the version number with every update, i.e.

    public void Update(MyClass document)
    {
        db.GetCollection<MyClass>("MyClass").Update(
            Query.And(
                Query<MyClass>.EQ(p => p.Id, document.Id), 
                Query<MyClass>(p => p.Version, document.Version),
                Update<MyClass>.Replace(document).Inc(p => p.Version));
    }
    

    Now let's suppose two threads A and B perform operations concurrently:

    • A read document id 8, version = 5
    • B read document id 8, version = 5
    • B store update id 8, version = 6
    • A attempt to store update on document id 8, version 5, but such an object no longer exists.

    MongoCollection<T>.Update returns a WriteConcernResult which has a property DocumentsAffected that you can use to check whether a document was updated, or not.

    Also see the MongoDB docs: Isolate Sequence of Operations