|
|
|
@ -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<TDbContext> : 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<TDbContext> : DbContext, IAbpEfCoreDbContext, |
|
|
|
onModelCreatingAction.As<Action<DbContext, ModelBuilder>>().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<TDbContext> : DbContext, IAbpEfCoreDbContext, |
|
|
|
AuditPropertySetter?.IncrementEntityVersionProperty(entry.Entity); |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual void ConfigureBaseProperties<TEntity>(ModelBuilder modelBuilder, IMutableEntityType mutableEntityType) |
|
|
|
protected virtual void ConfigureBaseProperties<TEntity>( |
|
|
|
ModelBuilder modelBuilder, |
|
|
|
IMutableEntityType mutableEntityType) |
|
|
|
where TEntity : class |
|
|
|
{ |
|
|
|
if (mutableEntityType.IsOwned()) |
|
|
|
@ -783,25 +785,44 @@ public abstract class AbpDbContext<TDbContext> : DbContext, IAbpEfCoreDbContext, |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
modelBuilder.Entity<TEntity>().ConfigureByConvention(); |
|
|
|
var entityTypeBuilder = CreateEntityTypeBuilderFromMutableEntityType<TEntity>( |
|
|
|
modelBuilder, |
|
|
|
mutableEntityType |
|
|
|
); |
|
|
|
|
|
|
|
entityTypeBuilder.ConfigureByConvention(); |
|
|
|
|
|
|
|
ConfigureGlobalFilters<TEntity>(modelBuilder, mutableEntityType, entityTypeBuilder); |
|
|
|
} |
|
|
|
|
|
|
|
ConfigureGlobalFilters<TEntity>(modelBuilder, mutableEntityType); |
|
|
|
protected virtual EntityTypeBuilder<TEntity> CreateEntityTypeBuilderFromMutableEntityType<TEntity>( |
|
|
|
ModelBuilder modelBuilder, |
|
|
|
IMutableEntityType mutableEntityType) where TEntity : class |
|
|
|
{ |
|
|
|
return mutableEntityType.HasSharedClrType |
|
|
|
? modelBuilder.SharedTypeEntity<TEntity>(mutableEntityType.Name) |
|
|
|
: modelBuilder.Entity<TEntity>(); |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual void ConfigureGlobalFilters<TEntity>(ModelBuilder modelBuilder, IMutableEntityType mutableEntityType) |
|
|
|
protected virtual void ConfigureGlobalFilters<TEntity>( |
|
|
|
ModelBuilder modelBuilder, |
|
|
|
IMutableEntityType mutableEntityType, |
|
|
|
EntityTypeBuilder<TEntity> entityTypeBuilder) |
|
|
|
where TEntity : class |
|
|
|
{ |
|
|
|
if (mutableEntityType.BaseType == null && ShouldFilterEntity<TEntity>(mutableEntityType)) |
|
|
|
{ |
|
|
|
var filterExpression = CreateFilterExpression<TEntity>(modelBuilder); |
|
|
|
var filterExpression = CreateFilterExpression<TEntity>(modelBuilder, entityTypeBuilder); |
|
|
|
if (filterExpression != null) |
|
|
|
{ |
|
|
|
modelBuilder.Entity<TEntity>().HasAbpQueryFilter(filterExpression); |
|
|
|
entityTypeBuilder.HasAbpQueryFilter(filterExpression); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual void ConfigureValueConverter<TEntity>(ModelBuilder modelBuilder, IMutableEntityType mutableEntityType) |
|
|
|
protected virtual void ConfigureValueConverter<TEntity>( |
|
|
|
ModelBuilder modelBuilder, |
|
|
|
IMutableEntityType mutableEntityType) |
|
|
|
where TEntity : class |
|
|
|
{ |
|
|
|
if (mutableEntityType.BaseType != null || |
|
|
|
@ -816,6 +837,7 @@ public abstract class AbpDbContext<TDbContext> : DbContext, IAbpEfCoreDbContext, |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
foreach (var property in mutableEntityType.GetProperties(). |
|
|
|
Where(property => property.PropertyInfo != null && |
|
|
|
@ -823,8 +845,12 @@ public abstract class AbpDbContext<TDbContext> : DbContext, IAbpEfCoreDbContext, |
|
|
|
property.PropertyInfo.CanWrite && |
|
|
|
ReflectionHelper.GetSingleAttributeOfMemberOrDeclaringTypeOrDefault<DisableDateTimeNormalizationAttribute>(property.PropertyInfo) == null)) |
|
|
|
{ |
|
|
|
modelBuilder |
|
|
|
.Entity<TEntity>() |
|
|
|
var entityTypeBuilder = CreateEntityTypeBuilderFromMutableEntityType<TEntity>( |
|
|
|
modelBuilder, |
|
|
|
mutableEntityType |
|
|
|
); |
|
|
|
|
|
|
|
entityTypeBuilder |
|
|
|
.Property(property.Name) |
|
|
|
.HasConversion(property.ClrType == typeof(DateTime) |
|
|
|
? new AbpDateTimeValueConverter(Clock) |
|
|
|
@ -832,7 +858,9 @@ public abstract class AbpDbContext<TDbContext> : DbContext, IAbpEfCoreDbContext, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual void ConfigureValueGenerated<TEntity>(ModelBuilder modelBuilder, IMutableEntityType mutableEntityType) |
|
|
|
protected virtual void ConfigureValueGenerated<TEntity>( |
|
|
|
ModelBuilder modelBuilder, |
|
|
|
IMutableEntityType mutableEntityType) |
|
|
|
where TEntity : class |
|
|
|
{ |
|
|
|
if (!typeof(IEntity<Guid>).IsAssignableFrom(typeof(TEntity))) |
|
|
|
@ -840,7 +868,8 @@ public abstract class AbpDbContext<TDbContext> : DbContext, IAbpEfCoreDbContext, |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
var idPropertyBuilder = modelBuilder.Entity<TEntity>().Property(x => ((IEntity<Guid>)x).Id); |
|
|
|
var entityTypeBuilder = CreateEntityTypeBuilderFromMutableEntityType<TEntity>(modelBuilder, mutableEntityType); |
|
|
|
var idPropertyBuilder = entityTypeBuilder.Property(x => ((IEntity<Guid>)x).Id); |
|
|
|
if (idPropertyBuilder.Metadata.PropertyInfo!.IsDefined(typeof(DatabaseGeneratedAttribute), true)) |
|
|
|
{ |
|
|
|
return; |
|
|
|
@ -864,25 +893,30 @@ public abstract class AbpDbContext<TDbContext> : DbContext, IAbpEfCoreDbContext, |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual Expression<Func<TEntity, bool>>? CreateFilterExpression<TEntity>(ModelBuilder modelBuilder) |
|
|
|
protected virtual Expression<Func<TEntity, bool>>? CreateFilterExpression<TEntity>( |
|
|
|
ModelBuilder modelBuilder, |
|
|
|
EntityTypeBuilder<TEntity> entityTypeBuilder) |
|
|
|
where TEntity : class |
|
|
|
{ |
|
|
|
Expression<Func<TEntity, bool>>? expression = null; |
|
|
|
|
|
|
|
if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity))) |
|
|
|
{ |
|
|
|
var softDeleteColumnName = modelBuilder.Entity<TEntity>().Metadata.FindProperty(nameof(ISoftDelete.IsDeleted))?.GetColumnName() ?? "IsDeleted"; |
|
|
|
var softDeleteColumnName = entityTypeBuilder.Metadata.FindProperty(nameof(ISoftDelete.IsDeleted))?.GetColumnName() ?? "IsDeleted"; |
|
|
|
expression = e => !IsSoftDeleteFilterEnabled || !EF.Property<bool>(e, softDeleteColumnName); |
|
|
|
if (UseDbFunction()) |
|
|
|
{ |
|
|
|
expression = e => AbpEfCoreDataFilterDbFunctionMethods.SoftDeleteFilter(((ISoftDelete)e).IsDeleted, true); |
|
|
|
modelBuilder.ConfigureSoftDeleteDbFunction(AbpEfCoreDataFilterDbFunctionMethods.SoftDeleteFilterMethodInfo, this.GetService<AbpEfCoreCurrentDbContext>()); |
|
|
|
modelBuilder.ConfigureSoftDeleteDbFunction( |
|
|
|
AbpEfCoreDataFilterDbFunctionMethods.SoftDeleteFilterMethodInfo, |
|
|
|
this.GetService<AbpEfCoreCurrentDbContext>() |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (typeof(IMultiTenant).IsAssignableFrom(typeof(TEntity))) |
|
|
|
{ |
|
|
|
var multiTenantColumnName = modelBuilder.Entity<TEntity>().Metadata.FindProperty(nameof(IMultiTenant.TenantId))?.GetColumnName() ?? "TenantId"; |
|
|
|
var multiTenantColumnName = entityTypeBuilder.Metadata.FindProperty(nameof(IMultiTenant.TenantId))?.GetColumnName() ?? "TenantId"; |
|
|
|
Expression<Func<TEntity, bool>> multiTenantFilter = e => !IsMultiTenantFilterEnabled || EF.Property<Guid>(e, multiTenantColumnName) == CurrentTenantId; |
|
|
|
if (UseDbFunction()) |
|
|
|
{ |
|
|
|
|