diff --git a/services/administration/src/EShopOnAbp.AdministrationService.HttpApi.Host/DbMigrations/AdministrationServiceDatabaseMigrationChecker.cs b/services/administration/src/EShopOnAbp.AdministrationService.HttpApi.Host/DbMigrations/AdministrationServiceDatabaseMigrationChecker.cs index 09c172d6..c99ac38b 100644 --- a/services/administration/src/EShopOnAbp.AdministrationService.HttpApi.Host/DbMigrations/AdministrationServiceDatabaseMigrationChecker.cs +++ b/services/administration/src/EShopOnAbp.AdministrationService.HttpApi.Host/DbMigrations/AdministrationServiceDatabaseMigrationChecker.cs @@ -1,13 +1,13 @@ using EShopOnAbp.AdministrationService.EntityFrameworkCore; -using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations; using System; +using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations.EfCore; using Volo.Abp.EventBus.Distributed; using Volo.Abp.MultiTenancy; using Volo.Abp.Uow; namespace EShopOnAbp.AdministrationService.DbMigrations { - public class AdministrationServiceDatabaseMigrationChecker : PendingMigrationsCheckerBase + public class AdministrationServiceDatabaseMigrationChecker : PendingEfCoreMigrationsChecker { public AdministrationServiceDatabaseMigrationChecker( IUnitOfWorkManager unitOfWorkManager, diff --git a/services/administration/src/EShopOnAbp.AdministrationService.HttpApi.Host/DbMigrations/AdministrationServiceDatabaseMigrationEventHandler.cs b/services/administration/src/EShopOnAbp.AdministrationService.HttpApi.Host/DbMigrations/AdministrationServiceDatabaseMigrationEventHandler.cs index b5f8c7d8..4640dfcf 100644 --- a/services/administration/src/EShopOnAbp.AdministrationService.HttpApi.Host/DbMigrations/AdministrationServiceDatabaseMigrationEventHandler.cs +++ b/services/administration/src/EShopOnAbp.AdministrationService.HttpApi.Host/DbMigrations/AdministrationServiceDatabaseMigrationEventHandler.cs @@ -1,8 +1,8 @@ using EShopOnAbp.AdministrationService.EntityFrameworkCore; -using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations; using System; using System.Linq; using System.Threading.Tasks; +using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations.EfCore; using Volo.Abp.Authorization.Permissions; using Volo.Abp.Data; using Volo.Abp.EventBus.Distributed; @@ -13,7 +13,7 @@ using Volo.Abp.Uow; namespace EShopOnAbp.AdministrationService.DbMigrations { public class AdministrationServiceDatabaseMigrationEventHandler - : DatabaseMigrationEventHandlerBase, + : DatabaseEfCoreMigrationEventHandler, IDistributedEventHandler, IDistributedEventHandler { diff --git a/services/catalog/EShopOnAbp.CatalogService.sln b/services/catalog/EShopOnAbp.CatalogService.sln index 42b4e1a5..90751a93 100644 --- a/services/catalog/EShopOnAbp.CatalogService.sln +++ b/services/catalog/EShopOnAbp.CatalogService.sln @@ -7,8 +7,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EShopOnAbp.CatalogService.D EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EShopOnAbp.CatalogService.Application", "src\EShopOnAbp.CatalogService.Application\EShopOnAbp.CatalogService.Application.csproj", "{1A94A50E-06DC-43C1-80B5-B662820EC3EB}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EShopOnAbp.CatalogService.EntityFrameworkCore", "src\EShopOnAbp.CatalogService.EntityFrameworkCore\EShopOnAbp.CatalogService.EntityFrameworkCore.csproj", "{C956DD76-69C8-4A9C-83EA-D17DF83340FD}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{CA9AC87F-097E-4F15-8393-4BC07735A5B0}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{04DBDB01-70F4-4E06-B468-8F87850B22BE}" @@ -23,8 +21,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EShopOnAbp.CatalogService.H EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EShopOnAbp.CatalogService.HttpApi.Client", "src\EShopOnAbp.CatalogService.HttpApi.Client\EShopOnAbp.CatalogService.HttpApi.Client.csproj", "{3B5A0094-670D-4BB1-BFDD-61B88A8773DC}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EShopOnAbp.CatalogService.EntityFrameworkCore.Tests", "test\EShopOnAbp.CatalogService.EntityFrameworkCore.Tests\EShopOnAbp.CatalogService.EntityFrameworkCore.Tests.csproj", "{1FE30EB9-74A9-47F5-A9F6-7B1FAB672D81}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EShopOnAbp.CatalogService.TestBase", "test\EShopOnAbp.CatalogService.TestBase\EShopOnAbp.CatalogService.TestBase.csproj", "{91853F21-9CD9-4132-BC29-A7D5D84FFFE7}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EShopOnAbp.CatalogService.Domain.Tests", "test\EShopOnAbp.CatalogService.Domain.Tests\EShopOnAbp.CatalogService.Domain.Tests.csproj", "{E512F4D9-9375-480F-A2F6-A46509F9D824}" @@ -33,6 +29,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EShopOnAbp.CatalogService.H EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EShopOnAbp.CatalogService.HttpApi.Host", "src\EShopOnAbp.CatalogService.HttpApi.Host\EShopOnAbp.CatalogService.HttpApi.Host.csproj", "{748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EShopOnAbp.CatalogService.MongoDB", "src\EShopOnAbp.CatalogService.MongoDB\EShopOnAbp.CatalogService.MongoDB.csproj", "{5D15000F-E6C4-45ED-96BC-6B6A029BA584}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EShopOnAbp.CatalogService.MongoDB.Tests", "test\EShopOnAbp.CatalogService.MongoDB.Tests\EShopOnAbp.CatalogService.MongoDB.Tests.csproj", "{353E567B-0519-4768-92DD-DC88E318E5B6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -47,10 +47,6 @@ Global {1A94A50E-06DC-43C1-80B5-B662820EC3EB}.Debug|Any CPU.Build.0 = Debug|Any CPU {1A94A50E-06DC-43C1-80B5-B662820EC3EB}.Release|Any CPU.ActiveCfg = Release|Any CPU {1A94A50E-06DC-43C1-80B5-B662820EC3EB}.Release|Any CPU.Build.0 = Release|Any CPU - {C956DD76-69C8-4A9C-83EA-D17DF83340FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C956DD76-69C8-4A9C-83EA-D17DF83340FD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C956DD76-69C8-4A9C-83EA-D17DF83340FD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C956DD76-69C8-4A9C-83EA-D17DF83340FD}.Release|Any CPU.Build.0 = Release|Any CPU {50B2631D-129C-47B3-A587-029CCD6099BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {50B2631D-129C-47B3-A587-029CCD6099BC}.Debug|Any CPU.Build.0 = Debug|Any CPU {50B2631D-129C-47B3-A587-029CCD6099BC}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -71,10 +67,6 @@ Global {3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Debug|Any CPU.Build.0 = Debug|Any CPU {3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Release|Any CPU.ActiveCfg = Release|Any CPU {3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Release|Any CPU.Build.0 = Release|Any CPU - {1FE30EB9-74A9-47F5-A9F6-7B1FAB672D81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1FE30EB9-74A9-47F5-A9F6-7B1FAB672D81}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1FE30EB9-74A9-47F5-A9F6-7B1FAB672D81}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1FE30EB9-74A9-47F5-A9F6-7B1FAB672D81}.Release|Any CPU.Build.0 = Release|Any CPU {91853F21-9CD9-4132-BC29-A7D5D84FFFE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {91853F21-9CD9-4132-BC29-A7D5D84FFFE7}.Debug|Any CPU.Build.0 = Debug|Any CPU {91853F21-9CD9-4132-BC29-A7D5D84FFFE7}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -91,6 +83,14 @@ Global {748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}.Debug|Any CPU.Build.0 = Debug|Any CPU {748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}.Release|Any CPU.ActiveCfg = Release|Any CPU {748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}.Release|Any CPU.Build.0 = Release|Any CPU + {5D15000F-E6C4-45ED-96BC-6B6A029BA584}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5D15000F-E6C4-45ED-96BC-6B6A029BA584}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5D15000F-E6C4-45ED-96BC-6B6A029BA584}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5D15000F-E6C4-45ED-96BC-6B6A029BA584}.Release|Any CPU.Build.0 = Release|Any CPU + {353E567B-0519-4768-92DD-DC88E318E5B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {353E567B-0519-4768-92DD-DC88E318E5B6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {353E567B-0519-4768-92DD-DC88E318E5B6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {353E567B-0519-4768-92DD-DC88E318E5B6}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -98,17 +98,17 @@ Global GlobalSection(NestedProjects) = preSolution {554AD327-6DBA-4F8F-96F8-81CE7A0C863F} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0} {1A94A50E-06DC-43C1-80B5-B662820EC3EB} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0} - {C956DD76-69C8-4A9C-83EA-D17DF83340FD} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0} {50B2631D-129C-47B3-A587-029CCD6099BC} = {04DBDB01-70F4-4E06-B468-8F87850B22BE} {42F719ED-8413-4895-B5B4-5AB56079BC66} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0} {520659C8-C734-4298-A3DA-B539DB9DFC0B} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0} {4164BDF7-F527-4E85-9CE6-E3C2D7426A27} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0} {3B5A0094-670D-4BB1-BFDD-61B88A8773DC} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0} - {1FE30EB9-74A9-47F5-A9F6-7B1FAB672D81} = {04DBDB01-70F4-4E06-B468-8F87850B22BE} {91853F21-9CD9-4132-BC29-A7D5D84FFFE7} = {04DBDB01-70F4-4E06-B468-8F87850B22BE} {E512F4D9-9375-480F-A2F6-A46509F9D824} = {04DBDB01-70F4-4E06-B468-8F87850B22BE} {EF480016-9127-4916-8735-D2466BDBC582} = {04DBDB01-70F4-4E06-B468-8F87850B22BE} {748584B1-BA69-4F6A-81AA-F4BDE6BCE29D} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0} + {5D15000F-E6C4-45ED-96BC-6B6A029BA584} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0} + {353E567B-0519-4768-92DD-DC88E318E5B6} = {04DBDB01-70F4-4E06-B468-8F87850B22BE} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {6AAFA1C6-603E-13FA-45E5-7910AA9F661D} diff --git a/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/EShopOnAbp.CatalogService.EntityFrameworkCore.csproj b/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/EShopOnAbp.CatalogService.EntityFrameworkCore.csproj deleted file mode 100644 index f5fa1c4c..00000000 --- a/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/EShopOnAbp.CatalogService.EntityFrameworkCore.csproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - net6.0 - EShopOnAbp.CatalogService - - - - - - - - - - - - - runtime; build; native; contentfiles; analyzers - compile; contentFiles; build; buildMultitargeting; buildTransitive; analyzers; native - - - - diff --git a/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/EntityFrameworkCore/CatalogServiceDbContext.cs b/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/EntityFrameworkCore/CatalogServiceDbContext.cs deleted file mode 100644 index d0a3d751..00000000 --- a/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/EntityFrameworkCore/CatalogServiceDbContext.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Volo.Abp.Data; -using Volo.Abp.EntityFrameworkCore; - -namespace EShopOnAbp.CatalogService.EntityFrameworkCore -{ - [ConnectionStringName(CatalogServiceDbProperties.ConnectionStringName)] - public class CatalogServiceDbContext : - AbpDbContext - { - /* Add DbSet properties for your Aggregate Roots / Entities here. */ - - public CatalogServiceDbContext(DbContextOptions options) - : base(options) - { - } - - protected override void OnModelCreating(ModelBuilder builder) - { - base.OnModelCreating(builder); - - /* Include modules to your migration db context */ - - /* Configure your own tables/entities inside here */ - - //builder.Entity(b => - //{ - // b.ToTable(CatalogServiceConsts.DbTablePrefix + "YourEntities", CatalogServiceConsts.DbSchema); - // b.ConfigureByConvention(); //auto configure for the base class props - // //... - //}); - } - } -} diff --git a/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/EntityFrameworkCore/CatalogServiceDbContextFactory.cs b/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/EntityFrameworkCore/CatalogServiceDbContextFactory.cs deleted file mode 100644 index 55b44780..00000000 --- a/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/EntityFrameworkCore/CatalogServiceDbContextFactory.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.IO; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Design; -using Microsoft.Extensions.Configuration; - -namespace EShopOnAbp.CatalogService.EntityFrameworkCore -{ - /* This class is needed for EF Core console commands - * (like Add-Migration and Update-Database commands) */ - public class CatalogServiceDbContextFactory : IDesignTimeDbContextFactory - { - public CatalogServiceDbContext CreateDbContext(string[] args) - { - CatalogServiceEfCoreEntityExtensionMappings.Configure(); - - var configuration = BuildConfiguration(); - - var builder = new DbContextOptionsBuilder() - .UseNpgsql( - configuration.GetConnectionString(CatalogServiceDbProperties.ConnectionStringName), - b => - { - b.MigrationsHistoryTable("__CatalogService_Migrations"); - }); - - return new CatalogServiceDbContext(builder.Options); - } - - private static IConfigurationRoot BuildConfiguration() - { - var builder = new ConfigurationBuilder() - .SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../EShopOnAbp.CatalogService.HttpApi.Host")) - .AddJsonFile("appsettings.json", optional: false); - - return builder.Build(); - } - } -} diff --git a/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/EntityFrameworkCore/CatalogServiceEfCoreEntityExtensionMappings.cs b/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/EntityFrameworkCore/CatalogServiceEfCoreEntityExtensionMappings.cs deleted file mode 100644 index 853e339f..00000000 --- a/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/EntityFrameworkCore/CatalogServiceEfCoreEntityExtensionMappings.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Volo.Abp.Threading; - -namespace EShopOnAbp.CatalogService.EntityFrameworkCore -{ - public static class CatalogServiceEfCoreEntityExtensionMappings - { - private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner(); - - public static void Configure() - { - OneTimeRunner.Run(() => - { - /* You can configure extra properties for the - * entities defined in the modules used by your application. - * - * This class can be used to map these extra properties to table fields in the database. - * - * USE THIS CLASS ONLY TO CONFIGURE EF CORE RELATED MAPPING. - * USE CatalogServiceModuleExtensionConfigurator CLASS (in the Domain.Shared project) - * FOR A HIGH LEVEL API TO DEFINE EXTRA PROPERTIES TO ENTITIES OF THE USED MODULES - * - * Example: Map a property to a table field: - - ObjectExtensionManager.Instance - .MapEfCoreProperty( - "MyProperty", - (entityBuilder, propertyBuilder) => - { - propertyBuilder.HasMaxLength(128); - } - ); - - * See the documentation for more: - * https://docs.abp.io/en/abp/latest/Customizing-Application-Modules-Extending-Entities - */ - }); - } - } -} diff --git a/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/EntityFrameworkCore/CatalogServiceEntityFrameworkCoreModule.cs b/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/EntityFrameworkCore/CatalogServiceEntityFrameworkCoreModule.cs deleted file mode 100644 index 62d8e651..00000000 --- a/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/EntityFrameworkCore/CatalogServiceEntityFrameworkCoreModule.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.EntityFrameworkCore; -using Volo.Abp.EntityFrameworkCore.PostgreSql; -using Volo.Abp.Modularity; - -namespace EShopOnAbp.CatalogService.EntityFrameworkCore -{ - [DependsOn( - typeof(CatalogServiceDomainModule), - typeof(AbpEntityFrameworkCorePostgreSqlModule) - )] - public class CatalogServiceEntityFrameworkCoreModule : AbpModule - { - public override void PreConfigureServices(ServiceConfigurationContext context) - { - CatalogServiceEfCoreEntityExtensionMappings.Configure(); - } - - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddAbpDbContext(options => - { - /* Remove "includeAllEntities: true" to create - * default repositories only for aggregate roots */ - options.AddDefaultRepositories(includeAllEntities: true); - }); - - Configure(options => - { - options.UseNpgsql(b => - { - b.MigrationsHistoryTable("__CatalogService_Migrations"); - }); - }); - } - } -} diff --git a/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/Migrations/20211125124215_Initial.Designer.cs b/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/Migrations/20211125124215_Initial.Designer.cs deleted file mode 100644 index 05f04edc..00000000 --- a/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/Migrations/20211125124215_Initial.Designer.cs +++ /dev/null @@ -1,30 +0,0 @@ -// -using EShopOnAbp.CatalogService.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using Volo.Abp.EntityFrameworkCore; - -#nullable disable - -namespace EShopOnAbp.CatalogService.Migrations -{ - [DbContext(typeof(CatalogServiceDbContext))] - [Migration("20211125124215_Initial")] - partial class Initial - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) - .HasAnnotation("ProductVersion", "6.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); -#pragma warning restore 612, 618 - } - } -} diff --git a/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/Migrations/20211125124215_Initial.cs b/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/Migrations/20211125124215_Initial.cs deleted file mode 100644 index aac30a21..00000000 --- a/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/Migrations/20211125124215_Initial.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace EShopOnAbp.CatalogService.Migrations -{ - public partial class Initial : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - - } - } -} diff --git a/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/Migrations/CatalogServiceDbContextModelSnapshot.cs b/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/Migrations/CatalogServiceDbContextModelSnapshot.cs deleted file mode 100644 index 6b110a46..00000000 --- a/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/Migrations/CatalogServiceDbContextModelSnapshot.cs +++ /dev/null @@ -1,28 +0,0 @@ -// -using EShopOnAbp.CatalogService.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; -using Volo.Abp.EntityFrameworkCore; - -#nullable disable - -namespace EShopOnAbp.CatalogService.Migrations -{ - [DbContext(typeof(CatalogServiceDbContext))] - partial class CatalogServiceDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.PostgreSql) - .HasAnnotation("ProductVersion", "6.0.0") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); -#pragma warning restore 612, 618 - } - } -} diff --git a/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/Properties/AssemblyInfo.cs b/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/Properties/AssemblyInfo.cs deleted file mode 100644 index 86e7b2d0..00000000 --- a/services/catalog/src/EShopOnAbp.CatalogService.EntityFrameworkCore/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,2 +0,0 @@ -using System.Runtime.CompilerServices; -[assembly:InternalsVisibleToAttribute("EShopOnAbp.CatalogService.EntityFrameworkCore.Tests")] diff --git a/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/CatalogServiceHttpApiHostModule.cs b/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/CatalogServiceHttpApiHostModule.cs index ca4bdc4a..37193d47 100644 --- a/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/CatalogServiceHttpApiHostModule.cs +++ b/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/CatalogServiceHttpApiHostModule.cs @@ -1,5 +1,4 @@ using EShopOnAbp.CatalogService.DbMigrations; -using EShopOnAbp.CatalogService.EntityFrameworkCore; using EShopOnAbp.Shared.Hosting.AspNetCore; using EShopOnAbp.Shared.Hosting.Microservices; using Microsoft.AspNetCore.Builder; @@ -9,6 +8,7 @@ using Microsoft.Extensions.Hosting; using System; using System.Collections.Generic; using System.Linq; +using EShopOnAbp.CatalogService.MongoDB; using Volo.Abp; using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.Modularity; @@ -19,7 +19,7 @@ namespace EShopOnAbp.CatalogService [DependsOn( typeof(CatalogServiceHttpApiModule), typeof(CatalogServiceApplicationModule), - typeof(CatalogServiceEntityFrameworkCoreModule), + typeof(CatalogServiceMongoDbModule), typeof(EShopOnAbpSharedHostingMicroservicesModule) )] public class CatalogServiceHttpApiHostModule : AbpModule diff --git a/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/DbMigrations/CatalogServiceDatabaseMigrationChecker.cs b/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/DbMigrations/CatalogServiceDatabaseMigrationChecker.cs index 5c085c40..1764271e 100644 --- a/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/DbMigrations/CatalogServiceDatabaseMigrationChecker.cs +++ b/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/DbMigrations/CatalogServiceDatabaseMigrationChecker.cs @@ -1,14 +1,13 @@ -using EShopOnAbp.CatalogService.EntityFrameworkCore; +using System; +using EShopOnAbp.CatalogService.MongoDB; using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations; -using System; -using System.Threading.Tasks; using Volo.Abp.EventBus.Distributed; using Volo.Abp.MultiTenancy; using Volo.Abp.Uow; namespace EShopOnAbp.CatalogService.DbMigrations { - public class CatalogServiceDatabaseMigrationChecker : PendingMigrationsCheckerBase + public class CatalogServiceDatabaseMigrationChecker : PendingMongoDbMigrationsChecker { public CatalogServiceDatabaseMigrationChecker( IUnitOfWorkManager unitOfWorkManager, diff --git a/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/DbMigrations/CatalogServiceDatabaseMigrationEventHandler.cs b/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/DbMigrations/CatalogServiceDatabaseMigrationEventHandler.cs index ee8cda8c..df17f17e 100644 --- a/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/DbMigrations/CatalogServiceDatabaseMigrationEventHandler.cs +++ b/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/DbMigrations/CatalogServiceDatabaseMigrationEventHandler.cs @@ -1,7 +1,8 @@ -using EShopOnAbp.CatalogService.EntityFrameworkCore; -using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations; +using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations; using System; using System.Threading.Tasks; +using EShopOnAbp.CatalogService.MongoDB; +using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations.MongoDb; using Volo.Abp.Data; using Volo.Abp.EventBus.Distributed; using Volo.Abp.MultiTenancy; @@ -10,20 +11,21 @@ using Volo.Abp.Uow; namespace EShopOnAbp.CatalogService.DbMigrations { public class CatalogServiceDatabaseMigrationEventHandler - : DatabaseMigrationEventHandlerBase, + : DatabaseMongoDbMigrationEventHandler, IDistributedEventHandler { public CatalogServiceDatabaseMigrationEventHandler( ICurrentTenant currentTenant, IUnitOfWorkManager unitOfWorkManager, ITenantStore tenantStore, - IDistributedEventBus distributedEventBus + IDistributedEventBus distributedEventBus, + IServiceProvider serviceProvider ) : base( currentTenant, unitOfWorkManager, tenantStore, distributedEventBus, - CatalogServiceDbProperties.ConnectionStringName) + CatalogServiceDbProperties.ConnectionStringName,serviceProvider) { } diff --git a/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/EShopOnAbp.CatalogService.HttpApi.Host.csproj b/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/EShopOnAbp.CatalogService.HttpApi.Host.csproj index 5024ad55..b7e561d5 100644 --- a/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/EShopOnAbp.CatalogService.HttpApi.Host.csproj +++ b/services/catalog/src/EShopOnAbp.CatalogService.HttpApi.Host/EShopOnAbp.CatalogService.HttpApi.Host.csproj @@ -11,7 +11,7 @@ - + diff --git a/services/catalog/src/EShopOnAbp.CatalogService.MongoDB/EShopOnAbp.CatalogService.MongoDB.csproj b/services/catalog/src/EShopOnAbp.CatalogService.MongoDB/EShopOnAbp.CatalogService.MongoDB.csproj new file mode 100644 index 00000000..071a43af --- /dev/null +++ b/services/catalog/src/EShopOnAbp.CatalogService.MongoDB/EShopOnAbp.CatalogService.MongoDB.csproj @@ -0,0 +1,15 @@ + + + + + + net6.0 + EShopOnAbp.CatalogService + + + + + + + + diff --git a/services/catalog/src/EShopOnAbp.CatalogService.MongoDB/MongoDB/CatalogServiceMongoDbContext.cs b/services/catalog/src/EShopOnAbp.CatalogService.MongoDB/MongoDB/CatalogServiceMongoDbContext.cs new file mode 100644 index 00000000..1174501a --- /dev/null +++ b/services/catalog/src/EShopOnAbp.CatalogService.MongoDB/MongoDB/CatalogServiceMongoDbContext.cs @@ -0,0 +1,20 @@ +using Volo.Abp.Data; +using Volo.Abp.MongoDB; + +namespace EShopOnAbp.CatalogService.MongoDB +{ + [ConnectionStringName(CatalogServiceDbProperties.ConnectionStringName)] + public class CatalogServiceMongoDbContext : AbpMongoDbContext, ICatalogServiceMongoDbContext + { + /* Add mongo collections here. Example: + * public IMongoCollection Questions => Collection(); + */ + + protected override void CreateModel(IMongoModelBuilder modelBuilder) + { + base.CreateModel(modelBuilder); + + modelBuilder.ConfigureCatalogService(); + } + } +} \ No newline at end of file diff --git a/services/catalog/src/EShopOnAbp.CatalogService.MongoDB/MongoDB/CatalogServiceMongoDbContextExtensions.cs b/services/catalog/src/EShopOnAbp.CatalogService.MongoDB/MongoDB/CatalogServiceMongoDbContextExtensions.cs new file mode 100644 index 00000000..5dca0500 --- /dev/null +++ b/services/catalog/src/EShopOnAbp.CatalogService.MongoDB/MongoDB/CatalogServiceMongoDbContextExtensions.cs @@ -0,0 +1,14 @@ +using Volo.Abp; +using Volo.Abp.MongoDB; + +namespace EShopOnAbp.CatalogService.MongoDB +{ + public static class CatalogServiceMongoDbContextExtensions + { + public static void ConfigureCatalogService( + this IMongoModelBuilder builder) + { + Check.NotNull(builder, nameof(builder)); + } + } +} diff --git a/services/catalog/src/EShopOnAbp.CatalogService.MongoDB/MongoDB/CatalogServiceMongoDbModule.cs b/services/catalog/src/EShopOnAbp.CatalogService.MongoDB/MongoDB/CatalogServiceMongoDbModule.cs new file mode 100644 index 00000000..b5d08c13 --- /dev/null +++ b/services/catalog/src/EShopOnAbp.CatalogService.MongoDB/MongoDB/CatalogServiceMongoDbModule.cs @@ -0,0 +1,23 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Modularity; +using Volo.Abp.MongoDB; + +namespace EShopOnAbp.CatalogService.MongoDB +{ + [DependsOn( + typeof(CatalogServiceDomainModule), + typeof(AbpMongoDbModule) + )] + public class CatalogServiceMongoDbModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddMongoDbContext(options => + { + /* Add custom repositories here. Example: + * options.AddRepository(); + */ + }); + } + } +} diff --git a/services/catalog/src/EShopOnAbp.CatalogService.MongoDB/MongoDB/ICatalogServiceMongoDbContext.cs b/services/catalog/src/EShopOnAbp.CatalogService.MongoDB/MongoDB/ICatalogServiceMongoDbContext.cs new file mode 100644 index 00000000..8dab1e0a --- /dev/null +++ b/services/catalog/src/EShopOnAbp.CatalogService.MongoDB/MongoDB/ICatalogServiceMongoDbContext.cs @@ -0,0 +1,13 @@ +using Volo.Abp.Data; +using Volo.Abp.MongoDB; + +namespace EShopOnAbp.CatalogService.MongoDB +{ + [ConnectionStringName(CatalogServiceDbProperties.ConnectionStringName)] + public interface ICatalogServiceMongoDbContext : IAbpMongoDbContext + { + /* Define mongo collections here. Example: + * IMongoCollection Questions { get; } + */ + } +} diff --git a/services/catalog/test/EShopOnAbp.CatalogService.Domain.Tests/CatalogServiceDomainCollection.cs b/services/catalog/test/EShopOnAbp.CatalogService.Domain.Tests/CatalogServiceDomainCollection.cs new file mode 100644 index 00000000..b0d3e0d8 --- /dev/null +++ b/services/catalog/test/EShopOnAbp.CatalogService.Domain.Tests/CatalogServiceDomainCollection.cs @@ -0,0 +1,10 @@ +using EShopOnAbp.CatalogService.MongoDB; +using Xunit; + +namespace EShopOnAbp.CatalogService; + +[CollectionDefinition(CatalogServiceTestConsts.CollectionDefinitionName)] +public class CatalogServiceDomainCollection : CatalogServiceMongoDbCollectionFixtureBase +{ + +} \ No newline at end of file diff --git a/services/catalog/test/EShopOnAbp.CatalogService.Domain.Tests/CatalogServiceDomainTestModule.cs b/services/catalog/test/EShopOnAbp.CatalogService.Domain.Tests/CatalogServiceDomainTestModule.cs index 65b5ea71..512d80ed 100644 --- a/services/catalog/test/EShopOnAbp.CatalogService.Domain.Tests/CatalogServiceDomainTestModule.cs +++ b/services/catalog/test/EShopOnAbp.CatalogService.Domain.Tests/CatalogServiceDomainTestModule.cs @@ -1,10 +1,10 @@ -using EShopOnAbp.CatalogService.EntityFrameworkCore; +using EShopOnAbp.CatalogService.MongoDB; using Volo.Abp.Modularity; namespace EShopOnAbp.CatalogService { [DependsOn( - typeof(CatalogServiceEntityFrameworkCoreTestModule) + typeof(CatalogServiceMongoDbTestModule) )] public class CatalogServiceDomainTestModule : AbpModule { diff --git a/services/catalog/test/EShopOnAbp.CatalogService.Domain.Tests/EShopOnAbp.CatalogService.Domain.Tests.csproj b/services/catalog/test/EShopOnAbp.CatalogService.Domain.Tests/EShopOnAbp.CatalogService.Domain.Tests.csproj index 96db1145..76ffe1aa 100644 --- a/services/catalog/test/EShopOnAbp.CatalogService.Domain.Tests/EShopOnAbp.CatalogService.Domain.Tests.csproj +++ b/services/catalog/test/EShopOnAbp.CatalogService.Domain.Tests/EShopOnAbp.CatalogService.Domain.Tests.csproj @@ -8,7 +8,7 @@ - + diff --git a/services/catalog/test/EShopOnAbp.CatalogService.EntityFrameworkCore.Tests/EntityFrameworkCore/CatalogServiceEntityFrameworkCoreTestBase.cs b/services/catalog/test/EShopOnAbp.CatalogService.EntityFrameworkCore.Tests/EntityFrameworkCore/CatalogServiceEntityFrameworkCoreTestBase.cs deleted file mode 100644 index 9b8ca18b..00000000 --- a/services/catalog/test/EShopOnAbp.CatalogService.EntityFrameworkCore.Tests/EntityFrameworkCore/CatalogServiceEntityFrameworkCoreTestBase.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Volo.Abp; - -namespace EShopOnAbp.CatalogService.EntityFrameworkCore -{ - public abstract class CatalogServiceEntityFrameworkCoreTestBase : CatalogServiceTestBase - { - - } -} diff --git a/services/catalog/test/EShopOnAbp.CatalogService.EntityFrameworkCore.Tests/EntityFrameworkCore/CatalogServiceEntityFrameworkCoreTestModule.cs b/services/catalog/test/EShopOnAbp.CatalogService.EntityFrameworkCore.Tests/EntityFrameworkCore/CatalogServiceEntityFrameworkCoreTestModule.cs deleted file mode 100644 index e1be3bb1..00000000 --- a/services/catalog/test/EShopOnAbp.CatalogService.EntityFrameworkCore.Tests/EntityFrameworkCore/CatalogServiceEntityFrameworkCoreTestModule.cs +++ /dev/null @@ -1,62 +0,0 @@ -using Microsoft.Data.Sqlite; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage; -using Microsoft.Extensions.DependencyInjection; -using Volo.Abp; -using Volo.Abp.EntityFrameworkCore; -using Volo.Abp.EntityFrameworkCore.Sqlite; -using Volo.Abp.Modularity; - -namespace EShopOnAbp.CatalogService.EntityFrameworkCore -{ - [DependsOn( - typeof(CatalogServiceEntityFrameworkCoreModule), - typeof(CatalogServiceTestBaseModule), - typeof(AbpEntityFrameworkCoreSqliteModule) - )] - public class CatalogServiceEntityFrameworkCoreTestModule : AbpModule - { - private SqliteConnection _sqliteConnection; - - public override void ConfigureServices(ServiceConfigurationContext context) - { - ConfigureInMemorySqlite(context.Services); - } - - private void ConfigureInMemorySqlite(IServiceCollection services) - { - _sqliteConnection = CreateDatabaseAndGetConnection(); - - services.Configure(options => - { - options.Configure(context => - { - context.DbContextOptions.UseSqlite(_sqliteConnection); - }); - }); - } - - public override void OnApplicationShutdown(ApplicationShutdownContext context) - { - _sqliteConnection.Dispose(); - } - - private static SqliteConnection CreateDatabaseAndGetConnection() - { - var connection = new SqliteConnection("Data Source=:memory:"); - connection.Open(); - - var options = new DbContextOptionsBuilder() - .UseSqlite(connection) - .Options; - - using (var context = new CatalogServiceDbContext(options)) - { - context.GetService().CreateTables(); - } - - return connection; - } - } -} diff --git a/services/catalog/test/EShopOnAbp.CatalogService.EntityFrameworkCore.Tests/EShopOnAbp.CatalogService.EntityFrameworkCore.Tests.csproj b/services/catalog/test/EShopOnAbp.CatalogService.MongoDB.Tests/EShopOnAbp.CatalogService.MongoDB.Tests.csproj similarity index 72% rename from services/catalog/test/EShopOnAbp.CatalogService.EntityFrameworkCore.Tests/EShopOnAbp.CatalogService.EntityFrameworkCore.Tests.csproj rename to services/catalog/test/EShopOnAbp.CatalogService.MongoDB.Tests/EShopOnAbp.CatalogService.MongoDB.Tests.csproj index 35e7b5b0..9236b367 100644 --- a/services/catalog/test/EShopOnAbp.CatalogService.EntityFrameworkCore.Tests/EShopOnAbp.CatalogService.EntityFrameworkCore.Tests.csproj +++ b/services/catalog/test/EShopOnAbp.CatalogService.MongoDB.Tests/EShopOnAbp.CatalogService.MongoDB.Tests.csproj @@ -7,14 +7,11 @@ EShopOnAbp.CatalogService - - - - - - + + + diff --git a/services/catalog/test/EShopOnAbp.CatalogService.MongoDB.Tests/MongoDB/CatalogServiceMongoCollection.cs b/services/catalog/test/EShopOnAbp.CatalogService.MongoDB.Tests/MongoDB/CatalogServiceMongoCollection.cs new file mode 100644 index 00000000..9da3075f --- /dev/null +++ b/services/catalog/test/EShopOnAbp.CatalogService.MongoDB.Tests/MongoDB/CatalogServiceMongoCollection.cs @@ -0,0 +1,9 @@ +using Xunit; + +namespace EShopOnAbp.CatalogService.MongoDB; + +[CollectionDefinition(CatalogServiceTestConsts.CollectionDefinitionName)] +public class CatalogServiceMongoCollection : CatalogServiceMongoDbCollectionFixtureBase +{ + +} \ No newline at end of file diff --git a/services/catalog/test/EShopOnAbp.CatalogService.MongoDB.Tests/MongoDB/CatalogServiceMongoDbCollectionFixtureBase.cs b/services/catalog/test/EShopOnAbp.CatalogService.MongoDB.Tests/MongoDB/CatalogServiceMongoDbCollectionFixtureBase.cs new file mode 100644 index 00000000..717b31ad --- /dev/null +++ b/services/catalog/test/EShopOnAbp.CatalogService.MongoDB.Tests/MongoDB/CatalogServiceMongoDbCollectionFixtureBase.cs @@ -0,0 +1,8 @@ +using Xunit; + +namespace EShopOnAbp.CatalogService.MongoDB; + +public class CatalogServiceMongoDbCollectionFixtureBase : ICollectionFixture +{ + +} \ No newline at end of file diff --git a/services/catalog/test/EShopOnAbp.CatalogService.MongoDB.Tests/MongoDB/CatalogServiceMongoDbFixture.cs b/services/catalog/test/EShopOnAbp.CatalogService.MongoDB.Tests/MongoDB/CatalogServiceMongoDbFixture.cs new file mode 100644 index 00000000..25e51904 --- /dev/null +++ b/services/catalog/test/EShopOnAbp.CatalogService.MongoDB.Tests/MongoDB/CatalogServiceMongoDbFixture.cs @@ -0,0 +1,22 @@ +using System; +using Mongo2Go; + +namespace EShopOnAbp.CatalogService.MongoDB +{ + public class CatalogServiceMongoDbFixture : IDisposable + { + private static readonly MongoDbRunner MongoDbRunner; + public static readonly string ConnectionString; + + static CatalogServiceMongoDbFixture() + { + MongoDbRunner = MongoDbRunner.Start(singleNodeReplSet: true, singleNodeReplSetWaitTimeout: 20); + ConnectionString = MongoDbRunner.ConnectionString; + } + + public void Dispose() + { + MongoDbRunner?.Dispose(); + } + } +} diff --git a/services/catalog/test/EShopOnAbp.CatalogService.MongoDB.Tests/MongoDB/CatalogServiceMongoDbTestBase.cs b/services/catalog/test/EShopOnAbp.CatalogService.MongoDB.Tests/MongoDB/CatalogServiceMongoDbTestBase.cs new file mode 100644 index 00000000..b5a2dbf9 --- /dev/null +++ b/services/catalog/test/EShopOnAbp.CatalogService.MongoDB.Tests/MongoDB/CatalogServiceMongoDbTestBase.cs @@ -0,0 +1,10 @@ +namespace EShopOnAbp.CatalogService.MongoDB +{ + /* This class can be used as a base class for MongoDB integration tests, + * while SampleRepository_Tests uses a different approach. + */ + public abstract class CatalogServiceMongoDbTestBase : CatalogServiceTestBase + { + + } +} \ No newline at end of file diff --git a/services/catalog/test/EShopOnAbp.CatalogService.MongoDB.Tests/MongoDB/CatalogServiceMongoDbTestModule.cs b/services/catalog/test/EShopOnAbp.CatalogService.MongoDB.Tests/MongoDB/CatalogServiceMongoDbTestModule.cs new file mode 100644 index 00000000..cd09e671 --- /dev/null +++ b/services/catalog/test/EShopOnAbp.CatalogService.MongoDB.Tests/MongoDB/CatalogServiceMongoDbTestModule.cs @@ -0,0 +1,27 @@ +using System; +using Volo.Abp.Data; +using Volo.Abp.Modularity; +using Volo.Abp.Uow; + +namespace EShopOnAbp.CatalogService.MongoDB +{ + [DependsOn( + typeof(CatalogServiceTestBaseModule), + typeof(CatalogServiceMongoDbModule) + )] + public class CatalogServiceMongoDbTestModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + var stringArray = CatalogServiceMongoDbFixture.ConnectionString.Split('?'); + var connectionString = stringArray[0].EnsureEndsWith('/') + + "Db_" + + Guid.NewGuid().ToString("N") + "/?" + stringArray[1]; + + Configure(options => + { + options.ConnectionStrings.Default = connectionString; + }); + } + } +} diff --git a/services/catalog/test/EShopOnAbp.CatalogService.TestBase/CatalogServiceTestConsts.cs b/services/catalog/test/EShopOnAbp.CatalogService.TestBase/CatalogServiceTestConsts.cs new file mode 100644 index 00000000..ca8e26ab --- /dev/null +++ b/services/catalog/test/EShopOnAbp.CatalogService.TestBase/CatalogServiceTestConsts.cs @@ -0,0 +1,6 @@ +namespace EShopOnAbp.CatalogService; + +public static class CatalogServiceTestConsts +{ + public const string CollectionDefinitionName = "CatalogService collection"; +} \ No newline at end of file diff --git a/services/identity/src/EShopOnAbp.IdentityService.HttpApi.Host/DbMigrations/IdentityServiceDatabaseMigrationChecker.cs b/services/identity/src/EShopOnAbp.IdentityService.HttpApi.Host/DbMigrations/IdentityServiceDatabaseMigrationChecker.cs index f09f9baa..75c16423 100644 --- a/services/identity/src/EShopOnAbp.IdentityService.HttpApi.Host/DbMigrations/IdentityServiceDatabaseMigrationChecker.cs +++ b/services/identity/src/EShopOnAbp.IdentityService.HttpApi.Host/DbMigrations/IdentityServiceDatabaseMigrationChecker.cs @@ -1,7 +1,7 @@ using EShopOnAbp.IdentityService.EntityFrameworkCore; -using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations; using System; using System.Threading.Tasks; +using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations.EfCore; using Volo.Abp.EventBus.Distributed; using Volo.Abp.EventBus.Local; using Volo.Abp.MultiTenancy; @@ -9,7 +9,7 @@ using Volo.Abp.Uow; namespace EShopOnAbp.IdentityService.DbMigrations { - public class IdentityServiceDatabaseMigrationChecker : PendingMigrationsCheckerBase + public class IdentityServiceDatabaseMigrationChecker : PendingEfCoreMigrationsChecker { protected ILocalEventBus LocalEventBus { get; } diff --git a/services/identity/src/EShopOnAbp.IdentityService.HttpApi.Host/DbMigrations/IdentityServiceDatabaseMigrationEventHandler.cs b/services/identity/src/EShopOnAbp.IdentityService.HttpApi.Host/DbMigrations/IdentityServiceDatabaseMigrationEventHandler.cs index f028b895..17d8dd98 100644 --- a/services/identity/src/EShopOnAbp.IdentityService.HttpApi.Host/DbMigrations/IdentityServiceDatabaseMigrationEventHandler.cs +++ b/services/identity/src/EShopOnAbp.IdentityService.HttpApi.Host/DbMigrations/IdentityServiceDatabaseMigrationEventHandler.cs @@ -1,9 +1,9 @@ using EShopOnAbp.IdentityService.EntityFrameworkCore; -using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations; using Serilog; using System; using System.Collections.Generic; using System.Threading.Tasks; +using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations.EfCore; using Volo.Abp.Data; using Volo.Abp.EventBus.Distributed; using Volo.Abp.EventBus.Local; @@ -14,7 +14,7 @@ using Volo.Abp.Uow; namespace EShopOnAbp.IdentityService.DbMigrations { public class IdentityServiceDatabaseMigrationEventHandler - : DatabaseMigrationEventHandlerBase, + : DatabaseEfCoreMigrationEventHandler, IDistributedEventHandler, IDistributedEventHandler { diff --git a/services/ordering/src/EShopOnAbp.OrderingService.HttpApi.Host/DbMigrations/OrderingServiceDatabaseMigrationChecker.cs b/services/ordering/src/EShopOnAbp.OrderingService.HttpApi.Host/DbMigrations/OrderingServiceDatabaseMigrationChecker.cs index 3acd7d62..ef8b92b9 100644 --- a/services/ordering/src/EShopOnAbp.OrderingService.HttpApi.Host/DbMigrations/OrderingServiceDatabaseMigrationChecker.cs +++ b/services/ordering/src/EShopOnAbp.OrderingService.HttpApi.Host/DbMigrations/OrderingServiceDatabaseMigrationChecker.cs @@ -1,13 +1,13 @@ using EShopOnAbp.OrderingService.EntityFrameworkCore; -using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations; using System; +using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations.EfCore; using Volo.Abp.EventBus.Distributed; using Volo.Abp.MultiTenancy; using Volo.Abp.Uow; namespace EShopOnAbp.OrderingService.DbMigrations { - public class OrderingServiceDatabaseMigrationChecker : PendingMigrationsCheckerBase + public class OrderingServiceDatabaseMigrationChecker : PendingEfCoreMigrationsChecker { public OrderingServiceDatabaseMigrationChecker( IUnitOfWorkManager unitOfWorkManager, diff --git a/services/ordering/src/EShopOnAbp.OrderingService.HttpApi.Host/DbMigrations/OrderingServiceDatabaseMigrationEventHandler.cs b/services/ordering/src/EShopOnAbp.OrderingService.HttpApi.Host/DbMigrations/OrderingServiceDatabaseMigrationEventHandler.cs index a6c61851..845ab7d6 100644 --- a/services/ordering/src/EShopOnAbp.OrderingService.HttpApi.Host/DbMigrations/OrderingServiceDatabaseMigrationEventHandler.cs +++ b/services/ordering/src/EShopOnAbp.OrderingService.HttpApi.Host/DbMigrations/OrderingServiceDatabaseMigrationEventHandler.cs @@ -1,7 +1,7 @@ using EShopOnAbp.OrderingService.EntityFrameworkCore; -using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations; using System; using System.Threading.Tasks; +using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations.EfCore; using Volo.Abp.Data; using Volo.Abp.EventBus.Distributed; using Volo.Abp.MultiTenancy; @@ -10,7 +10,7 @@ using Volo.Abp.Uow; namespace EShopOnAbp.OrderingService.DbMigrations { public class OrderingServiceDatabaseMigrationEventHandler - : DatabaseMigrationEventHandlerBase, + : DatabaseEfCoreMigrationEventHandler, IDistributedEventHandler { public OrderingServiceDatabaseMigrationEventHandler( diff --git a/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Host/DbMigrations/PaymentServiceDatabaseMigrationChecker.cs b/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Host/DbMigrations/PaymentServiceDatabaseMigrationChecker.cs index d771e75f..85c2a026 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Host/DbMigrations/PaymentServiceDatabaseMigrationChecker.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Host/DbMigrations/PaymentServiceDatabaseMigrationChecker.cs @@ -1,17 +1,13 @@ using EShopOnAbp.PaymentService.EntityFrameworkCore; -using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations; using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations.EfCore; using Volo.Abp.EventBus.Distributed; using Volo.Abp.MultiTenancy; using Volo.Abp.Uow; namespace EShopOnAbp.PaymentService.DbMigrations { - public class PaymentServiceDatabaseMigrationChecker : PendingMigrationsCheckerBase + public class PaymentServiceDatabaseMigrationChecker : PendingEfCoreMigrationsChecker { public PaymentServiceDatabaseMigrationChecker( IUnitOfWorkManager unitOfWorkManager, diff --git a/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Host/DbMigrations/PaymentServiceDatabaseMigrationEventHandler.cs b/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Host/DbMigrations/PaymentServiceDatabaseMigrationEventHandler.cs index 6b06f8b5..7fd87b4f 100644 --- a/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Host/DbMigrations/PaymentServiceDatabaseMigrationEventHandler.cs +++ b/services/payment/src/EShopOnAbp.PaymentService.HttpApi.Host/DbMigrations/PaymentServiceDatabaseMigrationEventHandler.cs @@ -1,7 +1,7 @@ using EShopOnAbp.PaymentService.EntityFrameworkCore; -using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations; using System; using System.Threading.Tasks; +using EShopOnAbp.Shared.Hosting.Microservices.DbMigrations.EfCore; using Volo.Abp.Data; using Volo.Abp.EventBus.Distributed; using Volo.Abp.MultiTenancy; @@ -10,7 +10,7 @@ using Volo.Abp.Uow; namespace EShopOnAbp.PaymentService.DbMigrations { public class PaymentServiceDatabaseMigrationEventHandler - : DatabaseMigrationEventHandlerBase, + : DatabaseEfCoreMigrationEventHandler, IDistributedEventHandler { public PaymentServiceDatabaseMigrationEventHandler( diff --git a/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/DatabaseMigrationEventHandlerBase.cs b/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/DatabaseMigrationEventHandlerBase.cs index 694c6479..dcaf6366 100644 --- a/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/DatabaseMigrationEventHandlerBase.cs +++ b/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/DatabaseMigrationEventHandlerBase.cs @@ -1,185 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using Serilog; -using Volo.Abp; -using Volo.Abp.Data; -using Volo.Abp.DependencyInjection; -using Volo.Abp.Domain.Entities.Events.Distributed; -using Volo.Abp.EntityFrameworkCore; -using Volo.Abp.EventBus.Distributed; -using Volo.Abp.MultiTenancy; -using Volo.Abp.Uow; +using Volo.Abp.DependencyInjection; -namespace EShopOnAbp.Shared.Hosting.Microservices.DbMigrations +namespace EShopOnAbp.Shared.Hosting.Microservices.DbMigrations; + +public abstract class DatabaseMigrationEventHandlerBase : ITransientDependency { - public abstract class DatabaseMigrationEventHandlerBase : - ITransientDependency - where TDbContext : DbContext, IEfCoreDbContext - { - protected const string TryCountPropertyName = "TryCount"; - protected const int MaxEventTryCount = 3; - - protected ICurrentTenant CurrentTenant { get; } - protected IUnitOfWorkManager UnitOfWorkManager { get; } - protected ITenantStore TenantStore { get; } - protected IDistributedEventBus DistributedEventBus { get; } - protected ILogger> Logger { get; set; } - protected string DatabaseName { get; } - - protected DatabaseMigrationEventHandlerBase( - ICurrentTenant currentTenant, - IUnitOfWorkManager unitOfWorkManager, - ITenantStore tenantStore, - IDistributedEventBus distributedEventBus, - string databaseName) - { - CurrentTenant = currentTenant; - UnitOfWorkManager = unitOfWorkManager; - TenantStore = tenantStore; - DatabaseName = databaseName; - DistributedEventBus = distributedEventBus; - - Logger = NullLogger>.Instance; - } - - /// - /// Apply pending EF Core schema migrations to the database. - /// Returns true if any migration has applied. - /// - protected virtual async Task MigrateDatabaseSchemaAsync(Guid? tenantId) - { - var result = false; - - using (CurrentTenant.Change(tenantId)) - { - using (var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: false)) - { - async Task MigrateDatabaseSchemaWithDbContextAsync() - { - var dbContext = await uow.ServiceProvider - .GetRequiredService>() - .GetDbContextAsync(); - - if ((await dbContext.Database.GetPendingMigrationsAsync()).Any()) - { - await dbContext.Database.MigrateAsync(); - return true; - } - - return false; - } - - if (tenantId == null) - { - //Migrating the host database - result = await MigrateDatabaseSchemaWithDbContextAsync(); - } - else - { - var tenantConfiguration = await TenantStore.FindAsync(tenantId.Value); - if (!tenantConfiguration.ConnectionStrings.Default.IsNullOrWhiteSpace() || - !tenantConfiguration.ConnectionStrings.GetOrDefault(DatabaseName).IsNullOrWhiteSpace()) - { - //Migrating the tenant database (only if tenant has a separate database) - result = await MigrateDatabaseSchemaWithDbContextAsync(); - } - } - - await uow.CompleteAsync(); - } - } - - return result; - } - - protected virtual async Task HandleErrorOnApplyDatabaseMigrationAsync( - ApplyDatabaseMigrationsEto eventData, - Exception exception) - { - var tryCount = IncrementEventTryCount(eventData); - if (tryCount <= MaxEventTryCount) - { - Log.Warning($"Could not apply database migrations. Re-queueing the operation. TenantId = {eventData.TenantId}, Database Name = {eventData.DatabaseName}."); - Log.Error(exception.ToString()); - - await Task.Delay(RandomHelper.GetRandom(5000, 15000)); - Log.Warning("Re publishing the event!"); - await DistributedEventBus.PublishAsync(eventData); - } - else - { - Log.Error($"Could not apply database migrations. Canceling the operation. TenantId = {eventData.TenantId}, DatabaseName = {eventData.DatabaseName}."); - Log.Error(exception.ToString()); - } - } - - protected virtual async Task HandleErrorTenantCreatedAsync( - TenantCreatedEto eventData, - Exception exception) - { - var tryCount = IncrementEventTryCount(eventData); - if (tryCount <= MaxEventTryCount) - { - Logger.LogWarning($"Could not perform tenant created event. Re-queueing the operation. TenantId = {eventData.Id}, TenantName = {eventData.Name}."); - Logger.LogException(exception, LogLevel.Warning); - - await Task.Delay(RandomHelper.GetRandom(5000, 15000)); - await DistributedEventBus.PublishAsync(eventData); - } - else - { - Logger.LogError($"Could not perform tenant created event. Canceling the operation. TenantId = {eventData.Id}, TenantName = {eventData.Name}."); - Logger.LogException(exception); - } - } - - protected virtual async Task HandleErrorTenantConnectionStringUpdatedAsync( - TenantConnectionStringUpdatedEto eventData, - Exception exception) - { - var tryCount = IncrementEventTryCount(eventData); - if (tryCount <= MaxEventTryCount) - { - Logger.LogWarning($"Could not perform tenant connection string updated event. Re-queueing the operation. TenantId = {eventData.Id}, TenantName = {eventData.Name}."); - Logger.LogException(exception, LogLevel.Warning); - - await Task.Delay(RandomHelper.GetRandom(5000, 15000)); - await DistributedEventBus.PublishAsync(eventData); - } - else - { - Logger.LogError($"Could not perform tenant connection string updated event. Canceling the operation. TenantId = {eventData.Id}, TenantName = {eventData.Name}."); - Logger.LogException(exception); - } - } - - private static int GetEventTryCount(EtoBase eventData) - { - var tryCountAsString = eventData.Properties.GetOrDefault(TryCountPropertyName); - if (tryCountAsString.IsNullOrEmpty()) - { - return 0; - } - - return int.Parse(tryCountAsString); - } - - private static void SetEventTryCount(EtoBase eventData, int count) - { - eventData.Properties[TryCountPropertyName] = count.ToString(); - } - - private static int IncrementEventTryCount(EtoBase eventData) - { - var count = GetEventTryCount(eventData) + 1; - SetEventTryCount(eventData, count); - return count; - } - } -} +} \ No newline at end of file diff --git a/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/EfCore/DatabaseEfCoreMigrationEventHandler.cs b/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/EfCore/DatabaseEfCoreMigrationEventHandler.cs new file mode 100644 index 00000000..298102b5 --- /dev/null +++ b/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/EfCore/DatabaseEfCoreMigrationEventHandler.cs @@ -0,0 +1,188 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Serilog; +using Volo.Abp; +using Volo.Abp.Data; +using Volo.Abp.Domain.Entities.Events.Distributed; +using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; + +namespace EShopOnAbp.Shared.Hosting.Microservices.DbMigrations.EfCore; + +public abstract class DatabaseEfCoreMigrationEventHandler : DatabaseMigrationEventHandlerBase + where TDbContext : DbContext, IEfCoreDbContext +{ + protected const string TryCountPropertyName = "TryCount"; + protected const int MaxEventTryCount = 3; + + protected ICurrentTenant CurrentTenant { get; } + protected IUnitOfWorkManager UnitOfWorkManager { get; } + protected ITenantStore TenantStore { get; } + protected IDistributedEventBus DistributedEventBus { get; } + protected ILogger> Logger { get; set; } + protected string DatabaseName { get; } + + protected DatabaseEfCoreMigrationEventHandler( + ICurrentTenant currentTenant, + IUnitOfWorkManager unitOfWorkManager, + ITenantStore tenantStore, + IDistributedEventBus distributedEventBus, + string databaseName) + { + CurrentTenant = currentTenant; + UnitOfWorkManager = unitOfWorkManager; + TenantStore = tenantStore; + DatabaseName = databaseName; + DistributedEventBus = distributedEventBus; + + Logger = NullLogger>.Instance; + } + + /// + /// Apply pending EF Core schema migrations to the database. + /// Returns true if any migration has applied. + /// + protected virtual async Task MigrateDatabaseSchemaAsync(Guid? tenantId) + { + var result = false; + + using (CurrentTenant.Change(tenantId)) + { + using (var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: false)) + { + async Task MigrateDatabaseSchemaWithDbContextAsync() + { + var dbContext = await uow.ServiceProvider + .GetRequiredService>() + .GetDbContextAsync(); + + if ((await dbContext.Database.GetPendingMigrationsAsync()).Any()) + { + await dbContext.Database.MigrateAsync(); + return true; + } + + return false; + } + + if (tenantId == null) + { + //Migrating the host database + result = await MigrateDatabaseSchemaWithDbContextAsync(); + } + else + { + var tenantConfiguration = await TenantStore.FindAsync(tenantId.Value); + if (!tenantConfiguration.ConnectionStrings.Default.IsNullOrWhiteSpace() || + !tenantConfiguration.ConnectionStrings.GetOrDefault(DatabaseName).IsNullOrWhiteSpace()) + { + //Migrating the tenant database (only if tenant has a separate database) + result = await MigrateDatabaseSchemaWithDbContextAsync(); + } + } + + await uow.CompleteAsync(); + } + } + + return result; + } + + protected virtual async Task HandleErrorOnApplyDatabaseMigrationAsync( + ApplyDatabaseMigrationsEto eventData, + Exception exception) + { + var tryCount = IncrementEventTryCount(eventData); + if (tryCount <= MaxEventTryCount) + { + Log.Warning( + $"Could not apply database migrations. Re-queueing the operation. TenantId = {eventData.TenantId}, Database Name = {eventData.DatabaseName}."); + Log.Error(exception.ToString()); + + await Task.Delay(RandomHelper.GetRandom(5000, 15000)); + Log.Warning("Re publishing the event!"); + await DistributedEventBus.PublishAsync(eventData); + } + else + { + Log.Error( + $"Could not apply database migrations. Canceling the operation. TenantId = {eventData.TenantId}, DatabaseName = {eventData.DatabaseName}."); + Log.Error(exception.ToString()); + } + } + + protected virtual async Task HandleErrorTenantCreatedAsync( + TenantCreatedEto eventData, + Exception exception) + { + var tryCount = IncrementEventTryCount(eventData); + if (tryCount <= MaxEventTryCount) + { + Logger.LogWarning( + $"Could not perform tenant created event. Re-queueing the operation. TenantId = {eventData.Id}, TenantName = {eventData.Name}."); + Logger.LogException(exception, LogLevel.Warning); + + await Task.Delay(RandomHelper.GetRandom(5000, 15000)); + await DistributedEventBus.PublishAsync(eventData); + } + else + { + Logger.LogError( + $"Could not perform tenant created event. Canceling the operation. TenantId = {eventData.Id}, TenantName = {eventData.Name}."); + Logger.LogException(exception); + } + } + + protected virtual async Task HandleErrorTenantConnectionStringUpdatedAsync( + TenantConnectionStringUpdatedEto eventData, + Exception exception) + { + var tryCount = IncrementEventTryCount(eventData); + if (tryCount <= MaxEventTryCount) + { + Logger.LogWarning( + $"Could not perform tenant connection string updated event. Re-queueing the operation. TenantId = {eventData.Id}, TenantName = {eventData.Name}."); + Logger.LogException(exception, LogLevel.Warning); + + await Task.Delay(RandomHelper.GetRandom(5000, 15000)); + await DistributedEventBus.PublishAsync(eventData); + } + else + { + Logger.LogError( + $"Could not perform tenant connection string updated event. Canceling the operation. TenantId = {eventData.Id}, TenantName = {eventData.Name}."); + Logger.LogException(exception); + } + } + + private static int GetEventTryCount(EtoBase eventData) + { + var tryCountAsString = eventData.Properties.GetOrDefault(TryCountPropertyName); + if (tryCountAsString.IsNullOrEmpty()) + { + return 0; + } + + return int.Parse(tryCountAsString); + } + + private static void SetEventTryCount(EtoBase eventData, int count) + { + eventData.Properties[TryCountPropertyName] = count.ToString(); + } + + private static int IncrementEventTryCount(EtoBase eventData) + { + var count = GetEventTryCount(eventData) + 1; + SetEventTryCount(eventData, count); + return count; + } +} \ No newline at end of file diff --git a/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/EfCore/PendingEfCoreMigrationsChecker.cs b/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/EfCore/PendingEfCoreMigrationsChecker.cs new file mode 100644 index 00000000..beea6577 --- /dev/null +++ b/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/EfCore/PendingEfCoreMigrationsChecker.cs @@ -0,0 +1,67 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Data; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; + +namespace EShopOnAbp.Shared.Hosting.Microservices.DbMigrations.EfCore; + +public abstract class PendingEfCoreMigrationsChecker : PendingMigrationsCheckerBase + where TDbContext : DbContext +{ + protected IUnitOfWorkManager UnitOfWorkManager { get; } + protected IServiceProvider ServiceProvider { get; } + protected ICurrentTenant CurrentTenant { get; } + protected IDistributedEventBus DistributedEventBus { get; } + protected string DatabaseName { get; } + + protected PendingEfCoreMigrationsChecker( + IUnitOfWorkManager unitOfWorkManager, + IServiceProvider serviceProvider, + ICurrentTenant currentTenant, + IDistributedEventBus distributedEventBus, + string databaseName) + { + UnitOfWorkManager = unitOfWorkManager; + ServiceProvider = serviceProvider; + CurrentTenant = currentTenant; + DistributedEventBus = distributedEventBus; + DatabaseName = databaseName; + } + + public virtual async Task CheckAsync() + { + var isMigrationRequired = false; + + using (CurrentTenant.Change(null)) + { + // Create database tables if needed + using (var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: false)) + { + var pendingMigrations = await ServiceProvider + .GetRequiredService() + .Database + .GetPendingMigrationsAsync(); + + if (pendingMigrations.Any()) + { + await DistributedEventBus.PublishAsync( + new ApplyDatabaseMigrationsEto + { + DatabaseName = DatabaseName + } + ); + isMigrationRequired = true; + } + + await uow.CompleteAsync(); + } + + return isMigrationRequired; + } + } +} \ No newline at end of file diff --git a/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/MongoDb/DatabaseMongoDbMigrationEventHandler.cs b/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/MongoDb/DatabaseMongoDbMigrationEventHandler.cs new file mode 100644 index 00000000..452cd7de --- /dev/null +++ b/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/MongoDb/DatabaseMongoDbMigrationEventHandler.cs @@ -0,0 +1,204 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using MongoDB.Driver; +using Volo.Abp; +using Volo.Abp.Data; +using Volo.Abp.Domain.Entities.Events.Distributed; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.MongoDB; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; + +namespace EShopOnAbp.Shared.Hosting.Microservices.DbMigrations.MongoDb; + +public abstract class DatabaseMongoDbMigrationEventHandler : DatabaseMigrationEventHandlerBase + where TDbContext : AbpMongoDbContext, IAbpMongoDbContext +{ + protected const string TryCountPropertyName = "TryCount"; + protected const int MaxEventTryCount = 3; + + protected ICurrentTenant CurrentTenant { get; } + protected IUnitOfWorkManager UnitOfWorkManager { get; } + protected ITenantStore TenantStore { get; } + protected IDistributedEventBus DistributedEventBus { get; } + protected ILogger> Logger { get; set; } + + protected IServiceProvider ServiceProvider { get; } + protected string DatabaseName { get; } + + protected DatabaseMongoDbMigrationEventHandler( + ICurrentTenant currentTenant, + IUnitOfWorkManager unitOfWorkManager, + ITenantStore tenantStore, + IDistributedEventBus distributedEventBus, + string databaseName, IServiceProvider serviceProvider) + { + CurrentTenant = currentTenant; + UnitOfWorkManager = unitOfWorkManager; + TenantStore = tenantStore; + DatabaseName = databaseName; + ServiceProvider = serviceProvider; + DistributedEventBus = distributedEventBus; + + Logger = NullLogger>.Instance; + } + + /// + /// Apply pending EF Core schema migrations to the database. + /// Returns true if any migration has applied. + /// + protected virtual async Task MigrateDatabaseSchemaAsync(Guid? tenantId) + { + var result = false; + + using (CurrentTenant.Change(tenantId)) + { + using (var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: false)) + { + async Task MigrateDatabaseSchemaWithDbContextAsync() + { + var dbContexts = ServiceProvider.GetServices(); + var connectionStringResolver = ServiceProvider.GetRequiredService(); + + foreach (var dbContext in dbContexts) + { + var connectionString = + await connectionStringResolver.ResolveAsync( + ConnectionStringNameAttribute.GetConnStringName(dbContext.GetType())); + if (connectionString.IsNullOrWhiteSpace()) + { + continue; + } + + var mongoUrl = new MongoUrl(connectionString); + var databaseName = mongoUrl.DatabaseName; + var client = new MongoClient(mongoUrl); + + if (databaseName.IsNullOrWhiteSpace()) + { + databaseName = ConnectionStringNameAttribute.GetConnStringName(dbContext.GetType()); + } + + (dbContext as AbpMongoDbContext)?.InitializeCollections(client.GetDatabase(databaseName)); + } + + return true; + } + + if (tenantId == null) + { + //Migrating the host database + result = await MigrateDatabaseSchemaWithDbContextAsync(); + } + else + { + var tenantConfiguration = await TenantStore.FindAsync(tenantId.Value); + if (!tenantConfiguration.ConnectionStrings.Default.IsNullOrWhiteSpace() || + !tenantConfiguration.ConnectionStrings.GetOrDefault(DatabaseName).IsNullOrWhiteSpace()) + { + //Migrating the tenant database (only if tenant has a separate database) + result = await MigrateDatabaseSchemaWithDbContextAsync(); + } + } + + await uow.CompleteAsync(); + } + } + + return result; + } + + protected virtual async Task HandleErrorOnApplyDatabaseMigrationAsync( + ApplyDatabaseMigrationsEto eventData, + Exception exception) + { + var tryCount = IncrementEventTryCount(eventData); + if (tryCount <= MaxEventTryCount) + { + Logger.LogWarning( + $"Could not apply database migrations. Re-queueing the operation. TenantId = {eventData.TenantId}, Database Name = {eventData.DatabaseName}."); + Logger.LogException(exception, LogLevel.Warning); + + await Task.Delay(RandomHelper.GetRandom(5000, 15000)); + await DistributedEventBus.PublishAsync(eventData); + } + else + { + Logger.LogError( + $"Could not apply database migrations. Canceling the operation. TenantId = {eventData.TenantId}, DatabaseName = {eventData.DatabaseName}."); + Logger.LogException(exception); + } + } + + protected virtual async Task HandleErrorTenantCreatedAsync( + TenantCreatedEto eventData, + Exception exception) + { + var tryCount = IncrementEventTryCount(eventData); + if (tryCount <= MaxEventTryCount) + { + Logger.LogWarning( + $"Could not perform tenant created event. Re-queueing the operation. TenantId = {eventData.Id}, TenantName = {eventData.Name}."); + Logger.LogException(exception, LogLevel.Warning); + + await Task.Delay(RandomHelper.GetRandom(5000, 15000)); + await DistributedEventBus.PublishAsync(eventData); + } + else + { + Logger.LogError( + $"Could not perform tenant created event. Canceling the operation. TenantId = {eventData.Id}, TenantName = {eventData.Name}."); + Logger.LogException(exception); + } + } + + protected virtual async Task HandleErrorTenantConnectionStringUpdatedAsync( + TenantConnectionStringUpdatedEto eventData, + Exception exception) + { + var tryCount = IncrementEventTryCount(eventData); + if (tryCount <= MaxEventTryCount) + { + Logger.LogWarning( + $"Could not perform tenant connection string updated event. Re-queueing the operation. TenantId = {eventData.Id}, TenantName = {eventData.Name}."); + Logger.LogException(exception, LogLevel.Warning); + + await Task.Delay(RandomHelper.GetRandom(5000, 15000)); + await DistributedEventBus.PublishAsync(eventData); + } + else + { + Logger.LogError( + $"Could not perform tenant connection string updated event. Canceling the operation. TenantId = {eventData.Id}, TenantName = {eventData.Name}."); + Logger.LogException(exception); + } + } + + private static int GetEventTryCount(EtoBase eventData) + { + var tryCountAsString = eventData.Properties.GetOrDefault(TryCountPropertyName); + if (tryCountAsString.IsNullOrEmpty()) + { + return 0; + } + + return int.Parse(tryCountAsString); + } + + private static void SetEventTryCount(EtoBase eventData, int count) + { + eventData.Properties[TryCountPropertyName] = count.ToString(); + } + + private static int IncrementEventTryCount(EtoBase eventData) + { + var count = GetEventTryCount(eventData) + 1; + SetEventTryCount(eventData, count); + return count; + } +} \ No newline at end of file diff --git a/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/MongoDb/PendingMongoDbMigrationsChecker.cs b/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/MongoDb/PendingMongoDbMigrationsChecker.cs new file mode 100644 index 00000000..61767f1f --- /dev/null +++ b/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/MongoDb/PendingMongoDbMigrationsChecker.cs @@ -0,0 +1,52 @@ +using System; +using System.Threading.Tasks; +using Volo.Abp.Data; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.MongoDB; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Uow; + +namespace EShopOnAbp.Shared.Hosting.Microservices.DbMigrations; + +public class PendingMongoDbMigrationsChecker : PendingMigrationsCheckerBase + where TDbContext : AbpMongoDbContext +{ + protected IUnitOfWorkManager UnitOfWorkManager { get; } + protected IServiceProvider ServiceProvider { get; } + protected ICurrentTenant CurrentTenant { get; } + protected IDistributedEventBus DistributedEventBus { get; } + protected string DatabaseName { get; } + + protected PendingMongoDbMigrationsChecker( + IUnitOfWorkManager unitOfWorkManager, + IServiceProvider serviceProvider, + ICurrentTenant currentTenant, + IDistributedEventBus distributedEventBus, + string databaseName) + { + UnitOfWorkManager = unitOfWorkManager; + ServiceProvider = serviceProvider; + CurrentTenant = currentTenant; + DistributedEventBus = distributedEventBus; + DatabaseName = databaseName; + } + + public virtual async Task CheckAsync() + { + using (CurrentTenant.Change(null)) + { + // Create database tables if needed + using (var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: false)) + { + await DistributedEventBus.PublishAsync( + new ApplyDatabaseMigrationsEto + { + DatabaseName = DatabaseName + } + ); + + await uow.CompleteAsync(); + } + } + } +} \ No newline at end of file diff --git a/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/PendingMigrationsCheckerBase.cs b/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/PendingMigrationsCheckerBase.cs index 7b168b75..492db8f1 100644 --- a/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/PendingMigrationsCheckerBase.cs +++ b/shared/EShopOnAbp.Shared.Hosting.Microservices/DbMigrations/PendingMigrationsCheckerBase.cs @@ -1,69 +1,8 @@ -using System; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.Data; -using Volo.Abp.DependencyInjection; -using Volo.Abp.EventBus.Distributed; -using Volo.Abp.MultiTenancy; -using Volo.Abp.Uow; +using Volo.Abp.DependencyInjection; namespace EShopOnAbp.Shared.Hosting.Microservices.DbMigrations { - public abstract class PendingMigrationsCheckerBase : ITransientDependency - where TDbContext : DbContext + public abstract class PendingMigrationsCheckerBase : ITransientDependency { - protected IUnitOfWorkManager UnitOfWorkManager { get; } - protected IServiceProvider ServiceProvider { get; } - protected ICurrentTenant CurrentTenant { get; } - protected IDistributedEventBus DistributedEventBus { get; } - protected string DatabaseName { get; } - - protected PendingMigrationsCheckerBase( - IUnitOfWorkManager unitOfWorkManager, - IServiceProvider serviceProvider, - ICurrentTenant currentTenant, - IDistributedEventBus distributedEventBus, - string databaseName) - { - UnitOfWorkManager = unitOfWorkManager; - ServiceProvider = serviceProvider; - CurrentTenant = currentTenant; - DistributedEventBus = distributedEventBus; - DatabaseName = databaseName; - } - - public virtual async Task CheckAsync() - { - var isMigrationRequired = false; - - using (CurrentTenant.Change(null)) - { - // Create database tables if needed - using (var uow = UnitOfWorkManager.Begin(requiresNew: true, isTransactional: false)) - { - var pendingMigrations = await ServiceProvider - .GetRequiredService() - .Database - .GetPendingMigrationsAsync(); - - if (pendingMigrations.Any()) - { - await DistributedEventBus.PublishAsync( - new ApplyDatabaseMigrationsEto - { - DatabaseName = DatabaseName - } - ); - isMigrationRequired = true; - } - - await uow.CompleteAsync(); - } - - return isMigrationRequired; - } - } } } \ No newline at end of file diff --git a/shared/EShopOnAbp.Shared.Hosting.Microservices/EShopOnAbp.Shared.Hosting.Microservices.csproj b/shared/EShopOnAbp.Shared.Hosting.Microservices/EShopOnAbp.Shared.Hosting.Microservices.csproj index e572f172..501d5e14 100644 --- a/shared/EShopOnAbp.Shared.Hosting.Microservices/EShopOnAbp.Shared.Hosting.Microservices.csproj +++ b/shared/EShopOnAbp.Shared.Hosting.Microservices/EShopOnAbp.Shared.Hosting.Microservices.csproj @@ -12,6 +12,7 @@ +