Using RavenDB Unit of Work and .NET Core MVC
We were asked about best practices for managing the RavenDB session (unit of work) in a .NET Core MVC application. I thought it is interesting enough to warrant its own post.
RavenDB’s client API is divided into the Document Store, which holds the overall configuration required to access a RavenDB and the Document Session, which is a short lived object implementing Unit of Work pattern and typically only used for a single request.
We’ll start by adding the RavenDB configuration to the appsettings.json file, like so:
We bind it to the following strongly typed configuration class:
The last thing to do it to register this with the container for dependency injection purposes:
We register both the Document Store and the Document Session in the container, but note that the session is registered on a scoped mode, so each connection will get a new session.
Finally, let’s make actual use of the session in a controller:
Note that we used to recommend having SaveChangesAsync run for you automatically, but at this time, I think it is probably better to do this explicitly.
Comments
I created a filter for doing Save automatically (https://github.com/RemiBou/Toss.Blazor/blob/master/Toss.Server/Data/RavenDBSaveAsyncActionFilter.cs) is that a bad practice for you ?
Related: you may be interested in RavenDB.DependencyInjection.
It lets you do what Ayende says here in the post, only with less code. Here's how it looks:
And you're done. There's also some optional extensions that let you custom load a certificate (e.g. from the cert store), as well as some overloads for configuring the doc store before initialization. It's available on NuGet as RavenDB.DependencyInjection.
@Remi, that's good: an action filter for Razor/Blazor pages to call .SaveChangesAsync(). In fact, I do exactly that in RavenDB.Identity Razor sample project. For MVC/API projects, I recommend a RavenController base class.
Remi, It depends on the team and the project. We found that some people didn't like this automatic behavior, and some adored it.
Oren - you might want to take a look at the constructor in the UserController class.
Randy, thanks, fixed
The patterns you posted are great and match the recommended approach from Microsoft. What I don't like is the template code in the controller.
When every controller uses session this code has to basically be copy-pasted in each one. Which I don't like that much.
Instead I made a BaseController
And RavenDBMiddleware
Which I invoke before app.UseMvc() in the Startup.cs Configure method.
This approach is quite similar to the old recommended approach with ASP.NET MVC and .NET 4.7
Comment preview