0

So I'm building an ASP.NET-Core API connecting to a mongoDB instance. I was reading through the official Microsoft tutorial regarding this topic and came across the linked code sample.

Basically they instantiate a BookService and create a new instance of MongoClient in the scope of the constructor.

private readonly IMongoCollection<Book> _books;

public BookService(IBookstoreDatabaseSettings settings)
{
    var client = new MongoClient(settings.ConnectionString);
    var database = client.GetDatabase(settings.DatabaseName);
    _books = database.GetCollection<Book>(settings.BooksCollectionName);
}

As I understand this the _books collection would still work without the MongoClient instance present since it knows which collection it's assigned to and how to communicate with it BUT the mongoDB MongoClient re-use guidelines suggests to store a global/static instance of the client to re-use. (I guess for the same port-exhaustion, etc. reason you would want to re-use HTTPClients? Also it supports internal connection pooling, which is nice!)

Thinking further on what they imply I was quite sure it would be a bad idea to instantiate and immediately drop an instance for a client for each of my services. But I dont't know anything about MongoDB on this scope.

I know it's just a tutorial and they tend to be the "quick and dirty" way of coding but since I'm new to this whole topic I just wanted to make sure I would start out properly.

So is it OK doing it the "Microsoft way" or should I just create a global instance for the client or a factory altogether?

//Edit:

For clarification: Would it be better to register the MongoClient as a Singleton on Startup and inject it into classes that need it OR use the method described above?

Nicolas
  • 425
  • 5
  • 11
  • 2
    Does this answer your question? [mongodb service - singleton or scoped?](https://stackoverflow.com/questions/59599151/mongodb-service-singleton-or-scoped) – Liam Mar 19 '21 at 10:54
  • 1
    Yes, it does! Thank you! – Nicolas Jul 27 '21 at 12:32

2 Answers2

2

This is how I typically add Mongo to my pipelines:

services.AddSingleton<IMongoClient>(sp =>
{ 
    var connectionString = "";
    return new MongoClient(connectionString);
});
services.AddScoped(sp =>
{
    var client = sp.GetRequiredService<IMongoClient>();
    var database = "";
    return client.GetDatabase(database);
});

This gives me a scoped IDatabase instance I can inject anywhere I need it (while using just one singleton IMongoClient instance).

crgolden
  • 3,974
  • 1
  • 19
  • 38
  • That looks nice! I might try that. Thank you! – Nicolas Aug 07 '20 at 18:16
  • could you please elaborate on that? What advantages does your pipeline have compared to simple ```var client = new MongoClient(connectionStr); services.AddScoped(_ => client.GetDatabase(dbName):``` ? – Nikita Fedorov Nov 30 '20 at 15:21
  • @Nikita Fedorov The advantage is that you can still access a singleton instance of `IMongoClient` anywhere else in your application (if you ever need to). – crgolden Nov 30 '20 at 19:12
0

Thank you for sharing, I am working on a MongoDB and .net core project. I have one DB with multiple collections. In start-up class

`services.AddSingleton(s => { return new MongoClient(con.ConnectionString).GetDatabase(con.DatabaseName); });`

My connection string and DB info are stored inside my appSetting.json. Now in my repo, I inject

mongoDBClient.GetCollection<SomeClass>(GetCollectionNameFromAppSetting((settings.CollectionName)));

Since I am having one Database would that be ok to have that registered as a singleton? or should I change it, Thank you