diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs index 882a51ebf1..fceb338051 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs @@ -37,6 +37,7 @@ using Volo.Abp.Reflection; using Volo.Abp.Timing; using Volo.Abp.Uow; using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace Volo.Abp.EntityFrameworkCore; @@ -126,7 +127,7 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, foreach (var entityType in modelBuilder.Model.GetEntityTypes().ToArray()) { - AutoConfigureEntityTypeProperties(modelBuilder, entityType); + ConfigureEntityTypeProperties(modelBuilder, entityType); } if (LazyServiceProvider == null || Options == null) @@ -140,24 +141,23 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, onModelCreatingAction.As>().Invoke(this, modelBuilder); } } - - protected virtual void AutoConfigureEntityTypeProperties( - ModelBuilder modelBuilder, - IMutableEntityType entityType) - { - ConfigureBasePropertiesMethodInfo - .MakeGenericMethod(entityType.ClrType) - .Invoke(this, new object[] { modelBuilder, entityType }); - - ConfigureValueConverterMethodInfo - .MakeGenericMethod(entityType.ClrType) - .Invoke(this, new object[] { modelBuilder, entityType }); - - ConfigureValueGeneratedMethodInfo - .MakeGenericMethod(entityType.ClrType) - .Invoke(this, new object[] { modelBuilder, entityType }); - } + protected virtual void ConfigureEntityTypeProperties( + ModelBuilder modelBuilder, + IMutableEntityType entityType) + { + ConfigureBasePropertiesMethodInfo + .MakeGenericMethod(entityType.ClrType) + .Invoke(this, new object[] { modelBuilder, entityType }); + + ConfigureValueConverterMethodInfo + .MakeGenericMethod(entityType.ClrType) + .Invoke(this, new object[] { modelBuilder, entityType }); + + ConfigureValueGeneratedMethodInfo + .MakeGenericMethod(entityType.ClrType) + .Invoke(this, new object[] { modelBuilder, entityType }); + } protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) { @@ -770,7 +770,9 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, AuditPropertySetter?.IncrementEntityVersionProperty(entry.Entity); } - protected virtual void ConfigureBaseProperties(ModelBuilder modelBuilder, IMutableEntityType mutableEntityType) + protected virtual void ConfigureBaseProperties( + ModelBuilder modelBuilder, + IMutableEntityType mutableEntityType) where TEntity : class { if (mutableEntityType.IsOwned()) @@ -783,25 +785,44 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, return; } - modelBuilder.Entity().ConfigureByConvention(); + var entityTypeBuilder = CreateEntityTypeBuilderFromMutableEntityType( + modelBuilder, + mutableEntityType + ); + + entityTypeBuilder.ConfigureByConvention(); + + ConfigureGlobalFilters(modelBuilder, mutableEntityType, entityTypeBuilder); + } - ConfigureGlobalFilters(modelBuilder, mutableEntityType); + protected virtual EntityTypeBuilder CreateEntityTypeBuilderFromMutableEntityType( + ModelBuilder modelBuilder, + IMutableEntityType mutableEntityType) where TEntity : class + { + return mutableEntityType.HasSharedClrType + ? modelBuilder.SharedTypeEntity(mutableEntityType.Name) + : modelBuilder.Entity(); } - protected virtual void ConfigureGlobalFilters(ModelBuilder modelBuilder, IMutableEntityType mutableEntityType) + protected virtual void ConfigureGlobalFilters( + ModelBuilder modelBuilder, + IMutableEntityType mutableEntityType, + EntityTypeBuilder entityTypeBuilder) where TEntity : class { if (mutableEntityType.BaseType == null && ShouldFilterEntity(mutableEntityType)) { - var filterExpression = CreateFilterExpression(modelBuilder); + var filterExpression = CreateFilterExpression(modelBuilder, entityTypeBuilder); if (filterExpression != null) { - modelBuilder.Entity().HasAbpQueryFilter(filterExpression); + entityTypeBuilder.HasAbpQueryFilter(filterExpression); } } } - protected virtual void ConfigureValueConverter(ModelBuilder modelBuilder, IMutableEntityType mutableEntityType) + protected virtual void ConfigureValueConverter( + ModelBuilder modelBuilder, + IMutableEntityType mutableEntityType) where TEntity : class { if (mutableEntityType.BaseType != null || @@ -816,6 +837,7 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, { return; } + foreach (var property in mutableEntityType.GetProperties(). Where(property => property.PropertyInfo != null && @@ -823,8 +845,12 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, property.PropertyInfo.CanWrite && ReflectionHelper.GetSingleAttributeOfMemberOrDeclaringTypeOrDefault(property.PropertyInfo) == null)) { - modelBuilder - .Entity() + var entityTypeBuilder = CreateEntityTypeBuilderFromMutableEntityType( + modelBuilder, + mutableEntityType + ); + + entityTypeBuilder .Property(property.Name) .HasConversion(property.ClrType == typeof(DateTime) ? new AbpDateTimeValueConverter(Clock) @@ -832,7 +858,9 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, } } - protected virtual void ConfigureValueGenerated(ModelBuilder modelBuilder, IMutableEntityType mutableEntityType) + protected virtual void ConfigureValueGenerated( + ModelBuilder modelBuilder, + IMutableEntityType mutableEntityType) where TEntity : class { if (!typeof(IEntity).IsAssignableFrom(typeof(TEntity))) @@ -840,7 +868,8 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, return; } - var idPropertyBuilder = modelBuilder.Entity().Property(x => ((IEntity)x).Id); + var entityTypeBuilder = CreateEntityTypeBuilderFromMutableEntityType(modelBuilder, mutableEntityType); + var idPropertyBuilder = entityTypeBuilder.Property(x => ((IEntity)x).Id); if (idPropertyBuilder.Metadata.PropertyInfo!.IsDefined(typeof(DatabaseGeneratedAttribute), true)) { return; @@ -864,25 +893,30 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, return false; } - protected virtual Expression>? CreateFilterExpression(ModelBuilder modelBuilder) + protected virtual Expression>? CreateFilterExpression( + ModelBuilder modelBuilder, + EntityTypeBuilder entityTypeBuilder) where TEntity : class { Expression>? expression = null; if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity))) { - var softDeleteColumnName = modelBuilder.Entity().Metadata.FindProperty(nameof(ISoftDelete.IsDeleted))?.GetColumnName() ?? "IsDeleted"; + var softDeleteColumnName = entityTypeBuilder.Metadata.FindProperty(nameof(ISoftDelete.IsDeleted))?.GetColumnName() ?? "IsDeleted"; expression = e => !IsSoftDeleteFilterEnabled || !EF.Property(e, softDeleteColumnName); if (UseDbFunction()) { expression = e => AbpEfCoreDataFilterDbFunctionMethods.SoftDeleteFilter(((ISoftDelete)e).IsDeleted, true); - modelBuilder.ConfigureSoftDeleteDbFunction(AbpEfCoreDataFilterDbFunctionMethods.SoftDeleteFilterMethodInfo, this.GetService()); + modelBuilder.ConfigureSoftDeleteDbFunction( + AbpEfCoreDataFilterDbFunctionMethods.SoftDeleteFilterMethodInfo, + this.GetService() + ); } } if (typeof(IMultiTenant).IsAssignableFrom(typeof(TEntity))) { - var multiTenantColumnName = modelBuilder.Entity().Metadata.FindProperty(nameof(IMultiTenant.TenantId))?.GetColumnName() ?? "TenantId"; + var multiTenantColumnName = entityTypeBuilder.Metadata.FindProperty(nameof(IMultiTenant.TenantId))?.GetColumnName() ?? "TenantId"; Expression> multiTenantFilter = e => !IsMultiTenantFilterEnabled || EF.Property(e, multiTenantColumnName) == CurrentTenantId; if (UseDbFunction()) {