简体   繁体   English

实体框架 DbContext 不使用依赖注入进行处置

[英]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我试过了

  • reordering 'AddTransient' without success (as expected)重新排序“AddTransient”但没有成功(如预期的那样)
  • using 'AddScoped' instead of 'AddTransient'使用“AddScoped”而不是“AddTransient”

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编辑:一些额外的日志

  • 2020-03-24 21:09:29.5727|Options injected in DataContext 2020-03-24 21:09:29.5727|在 DataContext 中注入的选项
  • 2020-03-24 21:09:29.6064|Authentication injected in DataContext 2020-03-24 21:09:29.6064|在 DataContext 中注入的身份验证
  • 2020-03-24 21:09:29.6064|Logger injected in DataContext 2020-03-24 21:09:29.6064|在 DataContext 中注入的记录器
  • 2020-03-24 21:09:29.6262| 2020-03-24 21:09:29.6262| Created DataContext 1ddd98a1-a8f9-4096-8a11-c0b4d40d01ae创建数据上下文 1ddd98a1-a8f9-4096-8a11-c0b4d40d01ae
  • 2020-03-24 21:09:30.1918|Logger injected in CustomerService 2020-03-24 21:09:30.1918|记录器注入客户服务
  • 2020-03-24 21:09:30.2200|DataContext injected in CustomerService 2020-03-24 21:09:30.2200|DataContext 注入 CustomerService
  • 2020-03-24 21:09:30.2300|Mapper injected in CustomerService 2020-03-24 21:09:30.2300|在客户服务中注入映射器
  • 2020-03-24 21:09:30.2482|Authentication injected in CustomerService 2020-03-24 21:09:30.2482|在 CustomerService 中注入的身份验证
  • 2020-03-24 21:09:30.2482| 2020-03-24 21:09:30.2482| Created CustomerService 5b446267-d908-4291-9918-af1841324708创建客户服务 5b446267-d908-4291-9918-af1841324708
  • 2020-03-24 21:09:30.2769|Logger injected in CustomerController 2020-03-24 21:09:30.2769|在 CustomerController 中注入的记录器
  • 2020-03-24 21:09:30.2769|CustomerService injected in CustomerController 2020-03-24 21:09:30.2769|CustomerService 在 CustomerController 中注入
  • 2020-03-24 21:09:30.3186|CustomerController.GetCustomer(4) 2020-03-24 21:09:30.3186|CustomerController.GetCustomer(4)
  • 2020-03-24 21:09:35.0599| 2020-03-24 21:09:35.0599| Disposing CustomerService 5b446267-d908-4291-9918-af1841324708处理 CustomerService 5b446267-d908-4291-9918-af1841324708

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM