efcore icon indicating copy to clipboard operation
efcore copied to clipboard

EFCore - DI - How to initialize service only once per unique DBContext

Open shvmgpt116 opened this issue 2 years ago • 2 comments

Dependency Injection allows services to be added in DI container in 3 ways (based on the service lifetime) Singleton, Scoped or Transient.

For a EFCore provider if someone wants a service to be created only once per unique db context, what would be the correct way to add the service to the container.

For Ex:- suppose a sample application is using 2 instances of same dbcontext

using (var context1 = new ModelContext())
{
...
...
}

using (var context2 = new ModelContext())
{
...
...
}

But there is a service 'X' which the EFCore provider implements and only want it to be initialized once per unique dbcontext. What would be the correct way to add the service to DI container.

Adding the service as Singleton would initialize the service only once during the lifetime of the application. So multiple instances of different dbcontext ( say ModelContext1 and ModelContext2) would also use the same service instance, which is not desirable.

Adding the service as Scoped would initialize the service for each instance of dbcontext (whether same or different). However I want to use the same service instance if dbcontext is same and different service instance if dbcontext is different. Is there some way to achieve this? Please could someone let me know.

Include provider and version information

EF Core version: 7.0.0 Database provider: Microsoft.EntityFrameworkCore.SqlServer Target framework: .NET 6.0 Operating system: Windows 10 IDE: Visual Studio 2022 17.4

shvmgpt116 avatar Jan 24 '23 18:01 shvmgpt116

Please could someone provide clarification. @ajcvickers

shvmgpt116 avatar Jan 25 '23 05:01 shvmgpt116

@shvmgpt116 As far as I know, this is not possible. You could instead create a singleton factory and have it create an instance per context type as needed.

ajcvickers avatar Jan 25 '23 23:01 ajcvickers

@ajcvickers Please could you provide me with an example how is it done.

shvmgpt116 avatar Feb 01 '23 10:02 shvmgpt116

@shvmgpt116 simply register a custom registry type that has a Dictionary<Type, T> as a singleton in your context, and have that injected wherever you need it. Then, simply look up the T given your context type.

roji avatar Feb 01 '23 11:02 roji

Note it should be a ConcurrentDictionary, or something else that will be thread safe, since the singleton service will be shared.

ajcvickers avatar Feb 01 '23 11:02 ajcvickers