Dependency Injection
IFinanceDbContext is defined in Application and implemented by FinanceDbContext in Infrastructure. DI connects the two, so Application never references the concrete class. Why the interface lives in Application is in Clean Architecture vs my design.
Infrastructure registers the DbContext
backend/src/ Finance.Infrastructure/ DependencyInjection.cs services.AddDbContext<FinanceDbContext>(options => options.UseNpgsql(configuration.GetConnectionString("FinanceDb")) ); services.AddScoped<IFinanceDbContext>(sp => sp.GetRequiredService<FinanceDbContext>()); return services;
AddDbContext()registersFinanceDbContextwith a scoped lifetime and configures PostgreSQL using theFinanceDbconnection string.AddScoped()mapsIFinanceDbContextto the registeredFinanceDbContext.spis theIServiceProvider, which resolves the same context instance within the request scope.return servicesreturns theIServiceCollectioncontaining the registrations, not the actual instances.
The API layer adds them to the container
backend/src/ Finance.Api/ Program.cs builder.Services.AddInfrastructure(builder.Configuration);
The API layer (Finance.Api) calls the Infrastructure registration method to add these dependencies to the application's DI container.
A service receives the interface
When ExpenseService requests IFinanceDbContext, DI supplies the configured FinanceDbContext. The database is accessed later when EF Core executes operations such as ToListAsync() or SaveChangesAsync().
Inspecting registered services
The following code can be added to backend/src/Finance.Api/Program.cs before builder.Build() to print registered service types and their lifetimes:
backend/src/ Finance.Api/ Program.cs foreach (var service in builder.Services) { Console.WriteLine($"Service: {service.ServiceType.Name}, " + $"Lifetime: {service.Lifetime}"); }
What to look for
FinanceDbContext should appear in the list as scoped.