skip to Main Content

How do I use Dependency Injection (.net8) to Inject two MongoBb Clients? I have a scenario where I need to read from Db1/collection1 and then save something to Db2/collection2. In my startup I have the following but not sure how to inject a second IMongoClient (both have different connection string)

services.AddSingleton<IMongoClient>x => new
    MongoClient(My_Server_Connection1));

services.AddSingleton<IMongoClient>x => new
    MongoClient(My_Server_Connection2));

I would like to be able to do something like this in my DataStore constructor

Db DataStore 1:

public DataStore1(IMongoClient clientWithConStr1, IMongoClient clientWithConStr2)
{
    database1 = clientWithConStr1.GetDatabase(DatabaseName1);
    database2 = clientWithConStr2.GetDatabase(DatabaseName1);
}
    

2

Answers


  1. MongoClient instance is not restricted to use a single database or collection which means that you can operate with as many dbs/collections as you want with a single client. So, I see no reasons to have dedicated instance in your case.

    Also, even though you create a 2 different MongoClient variables like:

    var inst1 = new MongoClient(); 
    var inst2 = new MongoClient();
    // inst1 == inst2;
    

    effectively it will be still a single instance as long as provided connection strings are the same. See my answer here for details.

    Don’t forget that when you create a mongo client, you effectively create a few background threads and some other shared resources like connection pool which, in turns, holds opened sockets, session pool and so on, so it’s heavy operation and it’s a good idea to reuse it.

    However, if you really want to distinguish these clients, configure ApplicationName option in MongoClientSettings or connectionString.

    UPDATE: If your question is only DI related, then consider Keyed service dependency injection, see this article:

    var builder = WebApplication.CreateBuilder(args);
    builder.Services.AddKeyedSingleton<IMongoClient, MongoClient>("connection1");
    builder.Services.AddKeyedSingleton<IMongoClient, MongoClient>("connection2");
    

    Consuming:

    public class Connection1Wrapper([FromKeyedServices("connection1")] IMongoClient client)
    {
        public string SomeWork(string message) => client.#some work#;
    }
    
    Login or Signup to reply.
  2. For your scenario to handle multiple MongoClients with different connection strings, it is better to implement a factory to select the MongoClient (provider) by type.

    1. An interface and class provider to initiate and retrive the MongoClient by type.
    public interface IMongoClientProvider
    {
        public int Type { get; }
    
        public IMongoClient GetMongoClient();
    }
    
    public class MongoClientProvider : IMongoClientProvider
    {
        public int Type { get; init; }
        private readonly IMongoClient _client;
    
        public MongoClientProvider(int type, string connectionString)
        {
            Type = type;
            _client = new MongoClient(connectionString);
        }
    
        public IMongoClient GetMongoClient()
        {
            return _client;
        }
    }
    
    1. A factory to select the MongoClientProvider by type`.
    using System.Collections.Generic;
    using System.Linq;
    
    public class MongoClientFactory
    {
        private readonly IEnumerable<IMongoClientProvider> _providers;
    
        public MongoClientFactory(IEnumerable<IMongoClientProvider> providers)
        {
            _providers = providers;
        }
    
        public MongoClient GetMongoClient(int type)
        {
            var provider = _providers.SingleOrDefault(x => x.Type == type);
            if (provider == null)
            {
                throw new Exception("Unsupported type for provider.");
            }
    
            return provider.GetMongoClient();
        }
    }
    
    1. Register the MongoClientProvider and MongoClientFactory into DI container.
    services.AddSingleton<IMongoClientProvider>(new MongoClientProvider(1, My_Server_Connection));
    services.AddSingleton<IMongoClientProvider>(new MongoClientProvider(2, My_Server_Connection2));
    
    services.AddSingleton<MongoClientFactory>();
    
    1. In the DataStore class, get the MongoClientFactory from the DI and retrieve the MongoClient instance by type.
    public class DataStore1
    {
        private readonly IMongoDatabase database;
        private readonly string databaseName = "DatabaseName1";
        
        public DataStore1(MongoClientFactory factory)
        {
            var client = factory.GetMongoClient(1);
            database = client.GetDatabase(databaseName);
        }
    }
    
    public class DataStore2
    {
        private readonly IMongoDatabase database;
        private readonly string databaseName = "DatabaseName2";
        
        public DataStore2(MongoClientFactory factory)
        {
            var client = factory.GetMongoClient(2);
            database = client.GetDatabase(databaseName);
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search