'Dependency Injection & connection strings / Multiple instances of a singleton

I have a Web Api project which relies heavily on Azure Cosmos DB. Until now, having one Cosmos DB account (one connection string) was sufficient. Now a new requirement is to be able to connect to a different Cosmos (two connection strings) depending on an incoming parameter.

For customerId X we should fetch documents from Cosmos DB 1 and for another customer Y we have to look in Cosmos DB 2.

Until now my Startup.cs file registered a singleton instance of CosmosClient. Which in turn gets instantiated like this cosmosClient = new CosmosClient(endpointUrl, primaryKey); And this worked really well. The Web Api was easily able to process all requests. But now that we have to new up a CosmosClient per request, performance is really bad.

So my question is; Is there a way to have multiple instances of the same singleton? As in; can we create a single instance of the combination Class+EndPointUrl? (Would that still be a singleton?)

Right now, we are newing up thousands of CosmosClients every minute. And we really need just one more compared to what we had earlier.



Solution 1:[1]

There's multiple ways to do this, but an easy implementation would be to create a wrapper around each CosmosClient you use. The only use of the wrapper will be to allow you to use various instances of the CosmosClient and differentiate them by their types.

//Create your own class for each client inheriting the behaviour of CosmosClient
public class ContosoCosmosClient : CosmosClient
{
    public ContosoCosmosClient(string connectionString, CosmosClientOptions clientOptions = null) : base(connectionString, clientOptions)
    {
    }

    public ContosoCosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions = null) : base(accountEndpoint, authKeyOrResourceToken, clientOptions)
    {
    }

    public ContosoCosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions = null) : base(accountEndpoint, tokenCredential, clientOptions)
    {
    }
}
//In Startup.up add a Singleton for each client
services.AddSingleton(new ContosoCosmosClient(...));
services.AddSingleton(new FabrikamCosmosClient(...));

Then in your business logic you can add both clients and depending on your logic choose which client you want to use:

public class MyService
{
    public MyService(ContosoCosmosClient contosoClient, FabrikamCosmosClient fabrikamClient)
    {
        //...
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 NotFound