.NET Core 3.0依赖注入不会关闭数据库集合

时间:2019-10-15 12:04:40

标签: api dependency-injection .net-core

我们正在尝试使用.NET Core 3.0在我们的API中实现依赖项注入。但是,我们存在一个小问题,即数据库连接没有以我们的方式关闭。简而言之,我们有一个带有DI设置的API项目,如下代码片段所示。理想情况下,我们希望能够使DI在初始化时将数据库上下文传递给我们的服务,然后自动关闭并随后处置此连接。

  

但是,即使连接具有“ 瞬态” ServiceLifetime,我们的连接也不会关闭,因此连接数一直累积到达到限制为止。

我们期望连接会自动关闭,我希望有人可以帮助我们对此有所了解?预先谢谢你:)

依赖注入设置代码:

using DatabaseORM.DbModels;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using PartnerArea.Partners;
using PartnerArea.PartnersOverviews;
using PartnerArea.PartnerGroups;
using PartnerArea.PartnerDetails;
using PartnerArea.PartnerCategories;
using PartnerArea.PartnerCustomColumns;
using PartnerArea.PartnerCustomColumnValuess;
using PartnerArea.PartnerOwners;
using UserArea.CurrentUser;
using UserArea.Contacts;
using AutoMapper;
using PartnerArea.PartnerStatuses;
using CompanyArea.CompanySettingss;
using PartnerArea.PartnerCategoryRelationss;

namespace BackendAPI
{
    public class DependencyInjectionStartupConfig
    {
        public DependencyInjectionStartupConfig(IServiceCollection services, IConfiguration Configuration)
        {
            SetupDbContexts(services, Configuration);
            SetupCurrentUsers(services);
            var sp = services.BuildServiceProvider();
            SetupRepositories(services, sp);
            sp = services.BuildServiceProvider();
            SetupServices(services, sp);
            sp = services.BuildServiceProvider();
            SetupServicesThatNeedOtherServices(services, sp);
        }
        public void SetupDbContexts(IServiceCollection services, IConfiguration Configuration)
        {
            services.AddDbContext<CoreContext>(options => options.UseSqlServer(Configuration.GetConnectionString("CoreDatabase")), ServiceLifetime.Transient);
        }

        public void SetupCurrentUsers(IServiceCollection services)
        {
            services.AddTransient<ICurrentUser>(s => new CurrentUser());
        }

        public void SetupRepositories(IServiceCollection services, ServiceProvider sp)
        {
            services.AddTransient<IPartnerRepository>(s => new PartnerRepository( sp.GetService<CoreContext>(), sp.GetService<ICurrentUser>()));
            services.AddTransient<IPartnerGroupRepository>(s => new PartnerGroupRepository( sp.GetService<CoreContext>(), sp.GetService<ICurrentUser>()));
            services.AddTransient<IPartnerCategoryRepository>(s => new PartnerCategoryRepository( sp.GetService<CoreContext>(), sp.GetService<ICurrentUser>()));
            services.AddTransient<IPartnerDetailRepository>(s => new PartnerDetailRepository( sp.GetService<CoreContext>(), sp.GetService<ICurrentUser>()));
            services.AddTransient<IPartnerOwnerRepository>(s => new PartnerOwnerRepository( sp.GetService<CoreContext>(), sp.GetService<ICurrentUser>()));
            services.AddTransient<IPartnerCustomColumnRepository>(s => new PartnerCustomColumnRepository( sp.GetService<CoreContext>(), sp.GetService<ICurrentUser>()));
            services.AddTransient<IPartnerCustomColumnValueRepository>(s => new PartnerCustomColumnValueRepository( sp.GetService<CoreContext>(), sp.GetService<ICurrentUser>()));
            services.AddTransient<IContactRepository>(s => new ContactRepository( sp.GetService<CoreContext>(), sp.GetService<ICurrentUser>()));
            services.AddTransient<IPartnerStatusRepository>(s => new PartnerStatusRepository( sp.GetService<CoreContext>(), sp.GetService<ICurrentUser>()));
            services.AddTransient<IPartnerOverviewRepository>(s => new PartnerOverviewRepository( sp.GetService<CoreContext>(), sp.GetService<ICurrentUser>()));
            services.AddTransient<ICompanySettingRepository>(s => new CompanySettingRepository( sp.GetService<CoreContext>(), sp.GetService<ICurrentUser>()));
            services.AddTransient<IPartnerCategoryRelationsRepository>(s => new PartnerCategoryRelationsRepository( sp.GetService<CoreContext>(), sp.GetService<ICurrentUser>()));
        }

        public void SetupServices(IServiceCollection services, ServiceProvider sp)
        {
            services.AddTransient<IPartnerServices>(s => new PartnerServices(sp.GetService<IPartnerRepository>(), sp.GetService<IMapper>()));
            services.AddTransient<IPartnerGroupServices>(s => new PartnerGroupServices(sp.GetService<IPartnerGroupRepository>(), sp.GetService<IPartnerRepository>(), sp.GetService<IMapper>()));
            services.AddTransient<IPartnerCategoryServices>(s => new PartnerCategoryServices(sp.GetService<IPartnerCategoryRepository>(), sp.GetService<IMapper>()));
            services.AddTransient<IPartnerDetailServices>(s => new PartnerDetailServices(sp.GetService<IPartnerDetailRepository>(), sp.GetService<IPartnerRepository>(), sp.GetService<IMapper>()));
            services.AddTransient<IPartnerOwnerServices>(s => new PartnerOwnerServices(sp.GetService<IPartnerOwnerRepository>(), sp.GetService<IMapper>()));
            services.AddTransient<IPartnerCustomColumnServices>(s => new PartnerCustomColumnServices(sp.GetService<IPartnerCustomColumnRepository>(), sp.GetService<IMapper>()));
            services.AddTransient<IPartnerCustomColumnValueServices>(s => new PartnerCustomColumnValueServices(sp.GetService<IPartnerRepository>(), sp.GetService<IPartnerCustomColumnValueRepository>(), sp.GetService<IMapper>()));
            services.AddTransient<IContactServices>(s => new ContactServices(sp.GetService<IContactRepository>(), sp.GetService<IMapper>()));
            services.AddTransient<IPartnerStatusServices>(s => new PartnerStatusServices(sp.GetService<IPartnerStatusRepository>(), sp.GetService<IPartnerRepository>(), sp.GetService<IMapper>()));
            services.AddTransient<IPartnersRelationServices>(s => new PartnersRelationServices(sp.GetService<IPartnerRepository>(), sp.GetService<IMapper>()));
            services.AddTransient<ICompanySettingServices>(s => new CompanySettingServices(sp.GetService<ICompanySettingRepository>(), sp.GetService<IMapper>()));
            services.AddTransient<IPartnerCategoryRelationsServices>(s => new PartnerCategoryRelationsServices(sp.GetService<IPartnerRepository>(), sp.GetService<IPartnerCategoryRelationsRepository>(), sp.GetService<IMapper>()));
        }

        public void SetupServicesThatNeedOtherServices(IServiceCollection services, ServiceProvider sp)
        {
            services.AddTransient<IPartnersOverviewServices>(s => new PartnersOverviewServices(sp.GetService<ICompanySettingServices>(), sp.GetService<IPartnerOverviewRepository>(), sp.GetService<IPartnerCustomColumnRepository>(), sp.GetService<IMapper>()));
        }
    }
}

1 个答案:

答案 0 :(得分:3)

不要手动创建存储库,为相应的存储库接口注册实现类型,DI也会创建一个具有必需依赖项(DbContext)的实例。

services.AddTransient<IPartnerRepository, PartnerRepository>();
services.AddTransient<IPartnerGroupRepository, PartnerGroupRepository>();

摘自文档“服务处置”:

  

容器调用Dispose为其创建的IDisposable类型。
  如果用户将实例添加到容器中   代码,它不会自动处理。

正如Nikosi在评论中指出的那样,您的案例中的DbContext和存储库实现是在根作用域DI容器(lambda函数获取“当前”根作用域上下文)中创建的,生命周期是应用程序的生命周期。当应用程序停止时,所有创建的实例将被“处置”。

通过注册存储库实现,您确保所有必需的实例都将由请求范围内的DI容器实例化,并在此DI容器超出范围(当请求完成)时将被处置。