I confess. It was a bit backwards writing about how to handle indexes in development involving multiple databases without writing about handling multiple databases. It’s never too late.
In RavenDB databases are a way to isolate, not only data, but configurations as well as the location of “physical” data. Oh, and it’s fully supported in server mode.
For the amounts of data my applications handle, we are good to go with a single database, but sometimes I have found the need to have separate databases. Hint: has to do with being faster to delete a complete database and start from scratch than delete lots of documents inside an existing one.
Once you have made the choice of having multiples databases you face the challenge of consuming those databases in code.
How I use RavenDB abstractions
The two main entry points for RavenDB are the
IDocumentStore and the
IDocumentSession (I have not had the chance to use asynchronous session yet) abstractions that are injected by the IOC Container of choice. IDocumentStore is expensive to create and I usually register it as a singleton. As for the IDocumentSession I usually have one instance per request which is disposed when the request ends.
The session is heavily tied to a database so, how does one handle having multiple instances around?
The database-specific session
It is easy enough to have a marker interface that extends IDocumentSession that represents an open session to a given database and use that dependency whenever a connection to a database is needed.
Question is, how is that abstraction implemented?
Some IOCs have the ability to create types on the fly, thus obviating the need of a concrete class that implements the specific session, but I have found those too tightly coupled to the IOC and pretty code-navigation unfriendly.
I would be silly, though, to create a type that implements the interface for each database: after all, one would be implementing IDocumentSession again and again and again. Instead we can use a decorator of the IDocumentSession interface can do the trick very well. The only thing one has to keep into account when instantiating the decorator is passing on the session to the correct database.
Small help offered
rvn-izr can help with this approach by providing the “implementation” for that decorator/adapter: the
DbSessionAdapter, that is.
The adapter implements IDocumentSession, but, in my experience, I have found this interface is kind of volatile (has changed in between versions). That kind of instability made me shy away from binary dependencies for this part of rvn-izr and go the source code route instead. With this approach, the adapters are integrated in the source code of the importer and use whichever version of RavenDB the importer is using.
Does that mean that the developer has to manually implement IDocumentSession? I am afraid so. Those twenty-something methods need to be implemented. Delegated, more properly speaking.
And you know what? It’s not a big deal. And with the right tools, one can achieve it in around 3 seconds, being a clumsy typist and even using the mouse. Here is how I do it with Resharper:
Closing the circle
And that is all. At least for sessions, for other database specific artifacts, head on to rvn-izr’s documentation and find out.