[Available via NuGet – MongoDB.Kennedy.Concurrency]
[Available via GitHub – optimistic_concurrency_mongodb_dotnet]
This article demonstrates a technique and supporting library for adding optimistic concurrency control to NoSQL databases and MongoDB in particular.
Watch a video walk-through using this library:
Quickly, what is optimistic concurrency control?
Ideally, all databases that allow concurrent access or disconnected access need to implement some form of concurrency control. This usually comes in two flavors:
Pessimistic concurrency control is usually used when working heavily within transactions. That may be fine for bank transfers, but it typically falls down in the face of disconnected models used by almost all ORMs such as Entity Framework. Moreover, it is entirely inappropriate for NoSQL databases.
Frameworks such as Entity Framework have optimistic concurrency control built in (although it may be turned off). It’s instructive to quickly see how it works. Basically there are three steps:
- Get an entity from the DB and disconnect.
- Edit in memory.
- Update the db with changes using a special update clause. Something like: “Update this row WHERE the current values are same as original values”.
If that update returns “0 rows modified” then we know it was changed since we loaded it and are about to overwrite someone’s changes. This results in a concurrency exception and not changes go through.
Optimistic concurrency control for MongoDB
By carefully constructing update commands in C# with the official 10gen C# driver, we can achieve almost exactly the same flow. At the end of this article is a simple C# class (data context) which has save and delete methods which internally are safe via optimistic concurrency control.
The only thing you need to do to use this library in your apps is to implement this interface on all top-level MongoDB entities and use a class derived from ConcurrentDataContext (in library below) for your data access.
Using this interface, the data context will manage a unique ID for you named _accessId per save. If someone else edits this object after you have gotten it but before saving it, you’ll get a concurrency exception, just like EF, and no changes will go through. All you do is call save and access entities via LINQ queries. Nice huh?
Here is an example of your entities with this interface in the db:
Here is an example of an app running end to end with only one editor on the document. See, no errors:
And here is simulating a concurrent edit, which results in an error.
Conclusion
There you have it! For all of you who want to adopt MongoDB and .NET but are concerned about concurrency issues, you now have the same level of concurrency safety as Entity Framework. That should be quite reassuring.
Download for the source, library with the concurrent data context, the sample app, and unit tests from GitHub:
https://github.com/mikeckennedy/optimistic_concurrency_mongodb_dotnet
Cheers,
@mkennedy