Reputation: 141
I have the following setup in a solution:
EDIT: Demo solution can be found here
ASP.NET Core Web API:
public class MyController : ControllerBase
{
private readonly IMyService _service;
public MyController(IMyService service)
{
_service = service;
}
}
Service layer:
public class MyService: IMyService, IDisposable
{
private readonly IDataContext _context;
public MyService(IDataContext context)
{
_context = context;
}
}
Entity Framework Core:
public class DataContext : DbContext, IDataContext, IDisposable
{
public DataContext(DbContextOptions<DataContext> options, IAuthenticationService authentication, ILogger<DataContext> logger) : base(options)
{
...
}
}
A 'CompositionRoot' to link it all together using Microsoft.Extensions.DependencyInjection:
services.AddDbContext<DataContext>(options => options.UseSqlServer(configuration.GetConnectionString("myConnection")), ServiceLifetime.Transient);
services.AddTransient<IMyService, MyService>();
//EDIT: removed this line
//services.AddTransient<IDataContext, DataContext>();
This all works as expected but my DataContext is never disposed. I've added logs in the dispose methods to monitor this behaviour but I can't figure out why this is happening (or not happening in this case). I've tried
I'm using an interface to mock the DbContext in my unit tests, but I want my DbContext to be disposed to. Anyone an idea on why this happens and how to solve it?
EDIT: some extra logs
EDIT march 25: I've tried using the DataContext without an interface but the problem still exists. I realy have no clue what I'm doing wrong!
Upvotes: 3
Views: 2061
Reputation: 21
Also faced with this issue (is it actually issue?). I have ASP.Net Core WebApi project (framework = net 5.0) and use AddDbContext to inject it to the MVC-Controller. It should add db-context as "Scoped" according to the article. As per my expectations, in this case db-context should be instantiated per every http request (that's it) and be disposed implicitly, in scope of MVC-Controller lifetime - but it's does not happen for some reason.. Potencially, it may result in "The instance of entity type {} cannot be tracked because another instance with the key value {} is already being tracked." (it's a reason why I have come here)
I belive, it may be fixed by added "using" construction in the code or by callind Dispose() from the Controller like that
protected override void Dispose(bool disposing = true)
{
Console.WriteLine("Controller dispose.");
_dbContext.Dispose(); //your db-context (injected in controller)
base.Dispose(disposing);
}
but not sure it's rigth solution..
Upvotes: 1
Reputation: 247561
You are not registering the DbContext correctly
Use the following overload of AddDbContext
services.AddDbContext<IDataContext, DataContext>(options =>
options.UseSqlServer(configuration.GetConnectionString("myConnection")));
Which will associate the interface/abstraction with the concrete implementation.
And remove the transient registration
services.AddTransient<IDataContext, DataContext>();
Upvotes: 2