From 40b3e3892e1afef5594ee36ae85053a6a2105b67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 29 Jan 2021 14:27:47 +0300 Subject: [PATCH 1/2] Added extension methods to ModelBuilder to know the multi-tenancy side for the current schema. --- .../AbpModelBuilderExtensions.cs | 72 +++++++++++++++++-- 1 file changed, 68 insertions(+), 4 deletions(-) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Microsoft/EntityFrameworkCore/AbpModelBuilderExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Microsoft/EntityFrameworkCore/AbpModelBuilderExtensions.cs index 7148cb69bd..1ccfee1506 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Microsoft/EntityFrameworkCore/AbpModelBuilderExtensions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Microsoft/EntityFrameworkCore/AbpModelBuilderExtensions.cs @@ -1,10 +1,72 @@ using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.MultiTenancy; namespace Microsoft.EntityFrameworkCore { public static class AbpModelBuilderExtensions { private const string ModelDatabaseProviderAnnotationKey = "_Abp_DatabaseProvider"; + private const string ModelMultiTenancySideAnnotationKey = "_Abp_MultiTenancySide"; + + #region MultiTenancySide + + public static void SetMultiTenancySide( + this ModelBuilder modelBuilder, + MultiTenancySides side) + { + modelBuilder.Model.SetAnnotation(ModelMultiTenancySideAnnotationKey, side); + } + + public static MultiTenancySides GetMultiTenancySide(this ModelBuilder modelBuilder) + { + var value = modelBuilder.Model[ModelMultiTenancySideAnnotationKey]; + if (value == null) + { + return MultiTenancySides.Both; + } + + return (MultiTenancySides) value; + } + + /// + /// Returns true if this is a database schema that is used by the host + /// but can also be shared with the tenants. + /// + public static bool IsHostDatabase(this ModelBuilder modelBuilder) + { + return modelBuilder.GetMultiTenancySide().HasFlag(MultiTenancySides.Host); + } + + /// + /// Returns true if this is a database schema that is used by the tenants + /// but can also be shared with the host. + /// + public static bool IsTenantDatabase(this ModelBuilder modelBuilder) + { + return modelBuilder.GetMultiTenancySide().HasFlag(MultiTenancySides.Tenant); + } + + /// + /// Returns true if this is a database schema that is only used by the host + /// and should not contain tenant-only tables. + /// + public static bool IsHostOnlyDatabase(this ModelBuilder modelBuilder) + { + return modelBuilder.GetMultiTenancySide() == MultiTenancySides.Host; + } + + /// + /// Returns true if this is a database schema that is only used by tenants. + /// and should not contain host-only tables. + /// + public static bool IsTenantOnlyDatabase(this ModelBuilder modelBuilder) + { + return modelBuilder.GetMultiTenancySide() == MultiTenancySides.Tenant; + } + + #endregion + + #region DatabaseProvider public static void SetDatabaseProvider( this ModelBuilder modelBuilder, @@ -61,7 +123,7 @@ namespace Microsoft.EntityFrameworkCore { modelBuilder.SetDatabaseProvider(EfCoreDatabaseProvider.InMemory); } - + public static bool IsUsingInMemory( this ModelBuilder modelBuilder) { @@ -73,7 +135,7 @@ namespace Microsoft.EntityFrameworkCore { modelBuilder.SetDatabaseProvider(EfCoreDatabaseProvider.Cosmos); } - + public static bool IsUsingCosmos( this ModelBuilder modelBuilder) { @@ -85,11 +147,13 @@ namespace Microsoft.EntityFrameworkCore { modelBuilder.SetDatabaseProvider(EfCoreDatabaseProvider.Firebird); } - + public static bool IsUsingFirebird( this ModelBuilder modelBuilder) { return modelBuilder.GetDatabaseProvider() == EfCoreDatabaseProvider.Firebird; } + + #endregion } -} \ No newline at end of file +} From 0c45c0e2ca227b95bd5a6dc675aad075a50b907d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 29 Jan 2021 14:42:16 +0300 Subject: [PATCH 2/2] Do not create host related tables in the tenant-only databases. --- ...undJobsDbContextModelCreatingExtensions.cs | 11 ++-- ...BloggingDbContextModelBuilderExtensions.cs | 5 ++ .../DocsDbContextModelBuilderExtensions.cs | 7 ++- ...agementDbContextModelCreatingExtensions.cs | 7 ++- ...IdentityDbContextModelBuilderExtensions.cs | 50 ++++++++++--------- ...yServerDbContextModelCreatingExtensions.cs | 5 ++ ...nagementDbContextModelBuilderExtensions.cs | 9 +++- ...agementDbContextModelCreatingExtensions.cs | 7 ++- 8 files changed, 70 insertions(+), 31 deletions(-) diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/BackgroundJobsDbContextModelCreatingExtensions.cs b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/BackgroundJobsDbContextModelCreatingExtensions.cs index 0d16130fb5..0e36a661f6 100644 --- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/BackgroundJobsDbContextModelCreatingExtensions.cs +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/BackgroundJobsDbContextModelCreatingExtensions.cs @@ -12,13 +12,18 @@ namespace Volo.Abp.BackgroundJobs.EntityFrameworkCore { Check.NotNull(builder, nameof(builder)); + if (builder.IsTenantOnlyDatabase()) + { + return; + } + var options = new BackgroundJobsModelBuilderConfigurationOptions( BackgroundJobsDbProperties.DbTablePrefix, BackgroundJobsDbProperties.DbSchema ); optionsAction?.Invoke(options); - + builder.Entity(b => { b.ToTable(options.TablePrefix + "BackgroundJobs", options.Schema); @@ -32,9 +37,9 @@ namespace Volo.Abp.BackgroundJobs.EntityFrameworkCore b.Property(x => x.LastTryTime); b.Property(x => x.IsAbandoned).HasDefaultValue(false); b.Property(x => x.Priority).HasDefaultValue(BackgroundJobPriority.Normal); - + b.HasIndex(x => new { x.IsAbandoned, x.NextTryTime }); }); } } -} \ No newline at end of file +} diff --git a/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/BloggingDbContextModelBuilderExtensions.cs b/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/BloggingDbContextModelBuilderExtensions.cs index a5e909d8a4..9c54d0a3a0 100644 --- a/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/BloggingDbContextModelBuilderExtensions.cs +++ b/modules/blogging/src/Volo.Blogging.EntityFrameworkCore/Volo/Blogging/EntityFrameworkCore/BloggingDbContextModelBuilderExtensions.cs @@ -20,6 +20,11 @@ namespace Volo.Blogging.EntityFrameworkCore { Check.NotNull(builder, nameof(builder)); + if (builder.IsTenantOnlyDatabase()) + { + return; + } + var options = new BloggingModelBuilderConfigurationOptions( BloggingDbProperties.DbTablePrefix, BloggingDbProperties.DbSchema diff --git a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContextModelBuilderExtensions.cs b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContextModelBuilderExtensions.cs index 379ca8792d..c751475728 100644 --- a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContextModelBuilderExtensions.cs +++ b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/EntityFrameworkCore/DocsDbContextModelBuilderExtensions.cs @@ -16,6 +16,11 @@ namespace Volo.Docs.EntityFrameworkCore { Check.NotNull(builder, nameof(builder)); + if (builder.IsTenantOnlyDatabase()) + { + return; + } + var options = new DocsModelBuilderConfigurationOptions( DocsDbProperties.DbTablePrefix, DocsDbProperties.DbSchema @@ -69,4 +74,4 @@ namespace Volo.Docs.EntityFrameworkCore }); } } -} \ No newline at end of file +} diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.EntityFrameworkCore/Volo/Abp/FeatureManagement/EntityFrameworkCore/FeatureManagementDbContextModelCreatingExtensions.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.EntityFrameworkCore/Volo/Abp/FeatureManagement/EntityFrameworkCore/FeatureManagementDbContextModelCreatingExtensions.cs index d854f89448..0398096b95 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.EntityFrameworkCore/Volo/Abp/FeatureManagement/EntityFrameworkCore/FeatureManagementDbContextModelCreatingExtensions.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.EntityFrameworkCore/Volo/Abp/FeatureManagement/EntityFrameworkCore/FeatureManagementDbContextModelCreatingExtensions.cs @@ -12,6 +12,11 @@ namespace Volo.Abp.FeatureManagement.EntityFrameworkCore { Check.NotNull(builder, nameof(builder)); + if (builder.IsTenantOnlyDatabase()) + { + return; + } + var options = new FeatureManagementModelBuilderConfigurationOptions( FeatureManagementDbProperties.DbTablePrefix, FeatureManagementDbProperties.DbSchema @@ -34,4 +39,4 @@ namespace Volo.Abp.FeatureManagement.EntityFrameworkCore }); } } -} \ No newline at end of file +} diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs index a533ce6340..4e43721a80 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs @@ -152,18 +152,21 @@ namespace Volo.Abp.Identity.EntityFrameworkCore b.HasIndex(uc => uc.RoleId); }); - builder.Entity(b => + if (builder.IsHostDatabase()) { - b.ToTable(options.TablePrefix + "ClaimTypes", options.Schema); + builder.Entity(b => + { + b.ToTable(options.TablePrefix + "ClaimTypes", options.Schema); - b.ConfigureByConvention(); + b.ConfigureByConvention(); - b.Property(uc => uc.Name).HasMaxLength(IdentityClaimTypeConsts.MaxNameLength) - .IsRequired(); // make unique - b.Property(uc => uc.Regex).HasMaxLength(IdentityClaimTypeConsts.MaxRegexLength); - b.Property(uc => uc.RegexDescription).HasMaxLength(IdentityClaimTypeConsts.MaxRegexDescriptionLength); - b.Property(uc => uc.Description).HasMaxLength(IdentityClaimTypeConsts.MaxDescriptionLength); - }); + b.Property(uc => uc.Name).HasMaxLength(IdentityClaimTypeConsts.MaxNameLength) + .IsRequired(); // make unique + b.Property(uc => uc.Regex).HasMaxLength(IdentityClaimTypeConsts.MaxRegexLength); + b.Property(uc => uc.RegexDescription).HasMaxLength(IdentityClaimTypeConsts.MaxRegexDescriptionLength); + b.Property(uc => uc.Description).HasMaxLength(IdentityClaimTypeConsts.MaxDescriptionLength); + }); + } builder.Entity(b => { @@ -233,22 +236,23 @@ namespace Volo.Abp.Identity.EntityFrameworkCore b.HasIndex(x => new { x.TenantId, x.UserId }); }); - builder.Entity(b => + if (builder.IsHostDatabase()) { - b.ToTable(options.TablePrefix + "LinkUsers", options.Schema); - - b.ConfigureByConvention(); - - b.HasIndex(x => new + builder.Entity(b => { - UserId = x.SourceUserId, - TenantId = x.SourceTenantId, - LinkedUserId = x.TargetUserId, - LinkedTenantId = x.TargetTenantId - }).IsUnique(); - }); - - + b.ToTable(options.TablePrefix + "LinkUsers", options.Schema); + + b.ConfigureByConvention(); + + b.HasIndex(x => new + { + UserId = x.SourceUserId, + TenantId = x.SourceTenantId, + LinkedUserId = x.TargetUserId, + LinkedTenantId = x.TargetTenantId + }).IsUnique(); + }); + } } } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IdentityServerDbContextModelCreatingExtensions.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IdentityServerDbContextModelCreatingExtensions.cs index 1759ce5855..d3d08dca15 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IdentityServerDbContextModelCreatingExtensions.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.EntityFrameworkCore/Volo/Abp/IdentityServer/EntityFrameworkCore/IdentityServerDbContextModelCreatingExtensions.cs @@ -19,6 +19,11 @@ namespace Volo.Abp.IdentityServer.EntityFrameworkCore { Check.NotNull(builder, nameof(builder)); + if (builder.IsTenantOnlyDatabase()) + { + return; + } + var options = new IdentityServerModelBuilderConfigurationOptions( AbpIdentityServerDbProperties.DbTablePrefix, AbpIdentityServerDbProperties.DbSchema diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo/Abp/SettingManagement/EntityFrameworkCore/SettingManagementDbContextModelBuilderExtensions.cs b/modules/setting-management/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo/Abp/SettingManagement/EntityFrameworkCore/SettingManagementDbContextModelBuilderExtensions.cs index 6f0bd5c3f8..0758cc9957 100644 --- a/modules/setting-management/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo/Abp/SettingManagement/EntityFrameworkCore/SettingManagementDbContextModelBuilderExtensions.cs +++ b/modules/setting-management/src/Volo.Abp.SettingManagement.EntityFrameworkCore/Volo/Abp/SettingManagement/EntityFrameworkCore/SettingManagementDbContextModelBuilderExtensions.cs @@ -27,6 +27,11 @@ namespace Volo.Abp.SettingManagement.EntityFrameworkCore { Check.NotNull(builder, nameof(builder)); + if (builder.IsTenantOnlyDatabase()) + { + return; + } + var options = new SettingManagementModelBuilderConfigurationOptions( AbpSettingManagementDbProperties.DbTablePrefix, AbpSettingManagementDbProperties.DbSchema @@ -44,7 +49,7 @@ namespace Volo.Abp.SettingManagement.EntityFrameworkCore if (builder.IsUsingOracle()) { SettingConsts.MaxValueLengthValue = 2000; } b.Property(x => x.Value).HasMaxLength(SettingConsts.MaxValueLengthValue).IsRequired(); - + b.Property(x => x.ProviderName).HasMaxLength(SettingConsts.MaxProviderNameLength); b.Property(x => x.ProviderKey).HasMaxLength(SettingConsts.MaxProviderKeyLength); @@ -52,4 +57,4 @@ namespace Volo.Abp.SettingManagement.EntityFrameworkCore }); } } -} \ No newline at end of file +} diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs b/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs index 03858df202..04c97046cf 100644 --- a/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs +++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.EntityFrameworkCore/Volo/Abp/TenantManagement/EntityFrameworkCore/AbpTenantManagementDbContextModelCreatingExtensions.cs @@ -13,6 +13,11 @@ namespace Volo.Abp.TenantManagement.EntityFrameworkCore { Check.NotNull(builder, nameof(builder)); + if (builder.IsTenantOnlyDatabase()) + { + return; + } + var options = new AbpTenantManagementModelBuilderConfigurationOptions( AbpTenantManagementDbProperties.DbTablePrefix, AbpTenantManagementDbProperties.DbSchema @@ -46,4 +51,4 @@ namespace Volo.Abp.TenantManagement.EntityFrameworkCore }); } } -} \ No newline at end of file +}