Multi tenancy (Multiple databases) and Singleton pattern

197 views
Skip to first unread message

Connor Aaron Roberts

unread,
Feb 14, 2021, 7:56:12 PM2/14/21
to RavenDB - 2nd generation document database
Hello,

While developing my program I've only used one database. It was very easy to use, I just copied and pasted the singleton document store pattern from the ravendb docs and its been working perfectly.

Now my application has changed and I need to use multiple databases. For the record, I don't use dependency injection or any IOC. 

I have 3 databases.
1. Accounts
2. Server1
3. Server2

My program has a json config file with the name of the database it needs to use. My program will always access the Accounts database, but it decides what database it needs to connect to between "Server1" and "Server2" based on the json config file. (I hope this makes sense).

I really would rather not pass the database name every time that I want to open a session. I think its too error prone this way. Do you have any recommendations about what I should do?

Egor Shamanaev

unread,
Feb 15, 2021, 4:37:09 AM2/15/21
to rav...@googlegroups.com
Hi 

There are two options that I can think of, 

1. Pass the database name to the session each time you don't want to use the store's default database.
https://ravendb.net/docs/article-page/4.2/csharp/client-api/session/opening-a-session#session-options

2. Create DocumentStoreHolder for each database and then use the stores accordingly
https://ravendb.net/docs/article-page/4.2/csharp/client-api/creating-document-store#creating-a-document-store---example

--
You received this message because you are subscribed to the Google Groups "RavenDB - 2nd generation document database" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ravendb+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ravendb/c2610875-c371-434b-9c8b-4ea6a6d3343fn%40googlegroups.com.


--
Egor
Developer   /   Hibernating Rhinos LTD
Support:  sup...@ravendb.net
  

Connor Aaron Roberts

unread,
Feb 15, 2021, 8:55:21 AM2/15/21
to rav...@googlegroups.com
Is there any disadvantage to creating a document store for each database? Because to be totally honest, it seems like the option that makes the most sense because it seems like the only way to do per-database configuration for the client. Thank you for your help

Ryan Heath

unread,
Feb 15, 2021, 12:24:54 PM2/15/21
to rav...@googlegroups.com
Are you using an ioc container or something like such?

You could then make it transparently for the code which database/session is being used, 
the decision which to use could be configured elsewhere. 

For example:

class CommonLogic (this class doesn't need to know which account db is being accessed)
{    
    public CommonLogic(IDocumentSession sessionCurrentAccount);
    public void DoLogic()
}

and in your registration, something like

ioc,Register<IDocumentSession>(services => {
    // determine which account is being access (for instance via current user or some other context
    var accountId = services.Get<ICurrentUser>().AccountId;
    // with accountId get the correct database and return a session for it
    var store = GetStoreFor(accountId);
    return store.OpenSession();
});

HTH

// Ryan






Connor Aaron Roberts

unread,
Feb 15, 2021, 1:35:41 PM2/15/21
to rav...@googlegroups.com
Not to be rude but if you read my question you would see I said that I'm not using dependency injection or IOC ^^ Thanks anyway

Oren Eini (Ayende Rahien)

unread,
Feb 16, 2021, 2:18:16 AM2/16/21
to ravendb
As long as they are singleton accesses and you don't have too many of them, there isn't an issue with having a document store per database.
Note that each document store will manage its own cache, so you may have more cache than expected



--
Oren Eini
CEO   /   Hibernating Rhinos LTD
Skype:  ayenderahien
Support:  sup...@ravendb.net
  

Ryan Heath

unread,
Feb 16, 2021, 3:08:56 AM2/16/21
to rav...@googlegroups.com
Whoops I missed that one hahaha. 

You might want to use some sort of factory pattern. Pass it to your common logic. The factory should know how to create the objects for a certain account. It keeps your common code clean and no need to pass account name or what so ever around. 

HTH (this time 😬)

// Ryan

Connor Aaron Roberts

unread,
Feb 16, 2021, 12:57:50 PM2/16/21
to rav...@googlegroups.com
Factory object for the DocumentStore or DocumentSession?

Ryan Heath

unread,
Feb 16, 2021, 1:19:27 PM2/16/21
to rav...@googlegroups.com
Would say for the DocumenSession.
Which store is to be used decided within the factory.

class Factory
    ctor Factory(AccountContext) // somehow you should know for which account you are going to do processing
    IDocumentSession CreateSession(){  /* access DocumentStore based on given AccountContext */ }

class CommonLogic
    ctor CommonLogic(Factory)
    void DoLogic()
    {
         using(factory.CreateSession())
         {
                ....
         }
     }

You could also move other account related stuff into the factory, 
so all decisions which account to use are within your factory.
But you could use another class if you want to keep the factory solely for DocumentSessions (RavenDB related)
it's a matter of taste and opinion.

HTH

// Ryan

Reply all
Reply to author
Forward
0 new messages