[英]Entity Framework DbContext is NOT disposed using dependency injection
I have the following setup in a solution:我在解决方案中有以下设置:
EDIT: Demo solution can be found here编辑:演示解决方案可以在这里找到
ASP.NET Core Web API: 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:使用 Microsoft.Extensions.DependencyInjection 将所有内容链接在一起的“CompositionRoot”:
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.这一切都按预期工作,但我的 DataContext 从未被处置。 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).
我在 dispose 方法中添加了日志来监视此行为,但我无法弄清楚为什么会发生这种情况(或者在这种情况下不会发生)。 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.我在我的单元测试中使用一个接口来模拟 DbContext,但我希望我的 DbContext 被处理。 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.编辑 3 月 25 日:我尝试使用没有接口的 DataContext,但问题仍然存在。 I realy have no clue what I'm doing wrong!
我真的不知道我做错了什么!
You are not registering the DbContext correctly您没有正确注册 DbContext
Use the following overload of AddDbContext
使用
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>();
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.
我有 ASP.Net Core WebApi 项目(框架 = net 5.0)并使用AddDbContext将其注入 MVC-Controller。 It should add db-context as "Scoped" according to the article.
根据文章,它应该将 db-context 添加为“Scoped”。 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)
根据我的期望,在这种情况下,db-context 应该根据每个 http 请求(就是这样)进行实例化,并在 MVC-Controller 生命周期的范围内隐式处理 - 但由于某种原因它不会发生.. 可能会导致在“无法跟踪实体类型 {} 的实例,因为已经在跟踪另一个具有键值 {} 的实例。 ”(这是我来这里的原因)
I belive, it may be fixed by added "using" construction in the code or by callind Dispose() from the Controller like that我相信,它可以通过在代码中添加“使用”结构或从控制器调用 Dispose() 来修复
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..但不确定这是正确的解决方案..
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.