Closed Rud156 closed 6 years ago
Hey @Rud156!
The ASP.NET Core docs cover this, although it's a little buried:
Entity Framework contexts should be added to the services container using the Scoped lifetime... Repositories that will make use of Entity Framework should use the same lifetime.
Here's an answer on StackOverflow that gives better detail: Entity Framework Core service default lifetime
In short, EF uses the Scoped lifetime so that the DbContext
gets disposed after every request. This means that each request is treated like a transaction unless you explicitly write your own transaction code. The request-as-transaction behavior is a nice default that works for many applications.
But is this the same case when using other databases also like MongoDB or CouchDB??
Most likely yes, although I think it depends on how you're using Mongo or Couch. Are you using them with EF, or using a package like mongo-csharp-driver to directly connect? If so, you'll need to think about connections, contexts, and transactions yourself. The right answer can depend on how the database driver works.
For example, the Mongo C# driver docs recommend that you create one MongoClient
and store it with a singleton-type lifetime. So, very similar. 😄
@nbarbettini Thanks a lot for the explanation. Will look into it
Let me know if you have further questions!
I am having this issue too, Lately, I started working on MongoDB. MongoDB recommends singleton for MongoClient. So I am still not sure about my implementation, and I am confused. I implemented the Mongo in DI container two ways, and I am not sure which one is good. Lets take the first approach
Here I return a singleton instance of IMongoClient
services.AddSingleton<IMongoClient>(_ =>
{
//var connectionString = con;
return new MongoClient(con.ConnectionString);
});
Then,
services.AddScoped<IMongoDatabase>(s =>
{
var client = p.GetRequiredService<IMongoClient>();
return client.GetDatabase(con.DatabaseName);
});
Then, return a scoped for my IMongoDatabase. In my repo, I inject the IMongoDatabaseand then call my DB.
_dataContext = mongoDBClient.GetCollection<SomeCollection>(GetCollectionNameFromAppSetting((settings.DPUBotCollectionName)));
The second one I was returning an IMongoDatabase as singleton:
services.AddSingleton<IMongoDatabase>(_ =>
{
//var connectionString = con;
return new MongoClient(con.ConnectionString).GetDatabase("SomeDatabase");
});
Monog says their MonogClient and IMongoDatabase are thread-safe. I am not sure which approach is right. I would appreciate it if you could give me an answer.
When the docs say,
It is recommended to store a MongoClient instance in a global place, either as a static variable or in an IoC container with a singleton lifetime. (...) The implementation of IMongoDatabase provided by a MongoClient is thread-safe and is safe to be stored globally or in an IoC container.
It means that you can use AddSingleton
for both of them.
Your 2nd example looks good to me, especially if you only ever have 1 database. Adding IMongoDatabase
as a singleton (the way you do in your 2nd example) ensures that the database connection is set up only once for the lifetime of the application, which is exactly in line with the recommendation.
I did not quite get when to use services.AddScoped or services.AddSingleton while using databases.
In the book it is mentioned that when using Entity Framework services.AddScoped is required because of the way Entity Framework handles requests. But is this the same case when using other databases also like MongoDB or CouchDB??
This Stackoverflow link describes the differences between them: https://stackoverflow.com/questions/38138100/what-is-the-difference-between-services-addtransient-service-addscope-and-servi
But the accepted way is not mentioned. Could you provide some better detail?