Внедрение зависимостей .NET Core 3.0 не закрывает коллекции БД - PullRequest
0 голосов
/ 15 октября 2019

Мы пытаемся внедрить внедрение зависимостей в наш API, используя .NET Core 3.0. Однако у нас есть небольшая проблема с соединениями с базой данных, которые не закрываются тем, как мы это делаем. Короче говоря, у нас есть наш проект API с настройкой DI, как показано ниже во фрагменте кода. В идеале мы хотели бы, чтобы DI передавал контекст базы данных нашим службам при инициализации, а затем автоматически закрывал и удалял это соединение.

Однако наши соединения не закрываются, даже несмотря на то, что он имеет « Transient » 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 Ответ

3 голосов
/ 15 октября 2019

Не создавайте репозитории вручную, зарегистрируйте тип реализации для соответствующего интерфейса репозитория, и DI создаст экземпляр с необходимыми зависимостями, а также DbContext.

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

Из документов "Утилизация служб":

Контейнер вызывает Dispose для создаваемых им типов IDisposable.
Если пользователь добавляет в контейнер экземпляркод, он не удаляется автоматически.

Как указал Никоси в комментариях, реализации DbContext и репозитория в вашем случае создаются в контейнере DI корневой области видимости (лямбда-функция захватывает «текущий» контекст корневой области видимости). ), время жизни которого - время жизни приложения. Все созданные экземпляры будут «утилизированы» после остановки приложения.

Регистрируя реализацию репозитория, вы гарантируете, что все необходимые экземпляры будут созданы экземпляром контейнера DI в области запроса и будут удалены, когда этот контейнер DI выйдет из области действия (когда запрос завершится).

...