From 92b3e3e324918b22464dde7161be7ca2afb05291 Mon Sep 17 00:00:00 2001 From: Salih Date: Thu, 7 Mar 2024 13:40:27 +0300 Subject: [PATCH 1/7] Allow extending ConfigureConventions and OnModelCreating --- .../Abp/EntityFrameworkCore/AbpDbContext.cs | 50 +++++++++++++++ .../AbpDbContextOptions.cs | 63 ++++++++++++++++++- 2 files changed, 112 insertions(+), 1 deletion(-) 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 b06ba191dd..de38a8bbf8 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs @@ -14,6 +14,7 @@ using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; using Volo.Abp.Auditing; using Volo.Abp.Data; using Volo.Abp.DependencyInjection; @@ -115,6 +116,55 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, .MakeGenericMethod(entityType.ClrType) .Invoke(this, new object[] { modelBuilder, entityType }); } + + var abpDbContextOptions = LazyServiceProvider.LazyGetRequiredService>().Value; + + var modelBuilderActions = abpDbContextOptions.ModelBuilderActions.GetOrDefault(typeof(TDbContext)); + if(modelBuilderActions == null) + { + return; + } + var actions = modelBuilderActions.OrderBy(a => a.Key).Select(a => a.Value).ToList(); + foreach (var action in actions) + { + if(action is Action modelBuilderAction) + { + modelBuilderAction.Invoke(modelBuilder, this); + } + + if(this is TDbContext dbContext && action is Action dbContextAction) + { + dbContextAction.Invoke(modelBuilder, dbContext); + } + } + } + + protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) + { + base.ConfigureConventions(configurationBuilder); + + var abpDbContextOptions = LazyServiceProvider.LazyGetRequiredService>().Value; + var conventions = abpDbContextOptions.Conventions.GetOrDefault(typeof(TDbContext)); + + if(conventions == null) + { + return; + } + + var actions = conventions.OrderBy(a => a.Key).Select(a => a.Value).ToList(); + + foreach (var action in actions) + { + if(action is Action modelBuilderAction) + { + modelBuilderAction.Invoke(configurationBuilder, this); + } + + if(this is TDbContext dbContext && action is Action dbContextAction) + { + dbContextAction.Invoke(configurationBuilder, dbContext); + } + } } protected virtual void TrySetDatabaseProvider(ModelBuilder modelBuilder) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs index cb5b258192..93de6a473c 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; using Volo.Abp.DependencyInjection; using Volo.Abp.EntityFrameworkCore.DependencyInjection; using Volo.Abp.MultiTenancy; @@ -20,12 +21,18 @@ public class AbpDbContextOptions internal Dictionary DbContextReplacements { get; } + internal Dictionary>> Conventions { get; } + + internal Dictionary>> ModelBuilderActions { get; } + public AbpDbContextOptions() { DefaultPreConfigureActions = new List>(); PreConfigureActions = new Dictionary>(); ConfigureActions = new Dictionary(); DbContextReplacements = new Dictionary(); + Conventions = new Dictionary>>(); + ModelBuilderActions = new Dictionary>>(); } public void PreConfigure([NotNull] Action action) @@ -41,6 +48,60 @@ public class AbpDbContextOptions DefaultConfigureAction = action; } + + public void ConfigureConventions([NotNull] Action action, Type? dbContextType = null, int? order = null) + { + Check.NotNull(action, nameof(action)); + + var actions = Conventions.GetOrDefault(dbContextType ?? typeof(AbpDbContext<>)); + if (actions == null) + { + Conventions[dbContextType ?? typeof(AbpDbContext<>)] = actions = new List>(); + } + + actions.Add(new KeyValuePair(order, action)); + } + + public void ConfigureConventions([NotNull] Action action, int? order = null) + where TDbContext : AbpDbContext + { + Check.NotNull(action, nameof(action)); + + var actions = Conventions.GetOrDefault(typeof(TDbContext)); + if (actions == null) + { + Conventions[typeof(TDbContext)] = actions = new List>(); + } + + actions.Add(new KeyValuePair(order, action)); + } + + public void OnModelCreating([NotNull] Action action, Type? dbContextType = null, int? order = null) + { + Check.NotNull(action, nameof(action)); + + var actions = ModelBuilderActions.GetOrDefault(dbContextType ?? typeof(AbpDbContext<>)); + if (actions == null) + { + ModelBuilderActions[dbContextType ?? typeof(AbpDbContext<>)] = actions = new List>(); + } + + actions.Add(new KeyValuePair(order, action)); + } + + public void OnModelCreating([NotNull] Action action, int? order = null) + where TDbContext : AbpDbContext + { + Check.NotNull(action, nameof(action)); + + var actions = ModelBuilderActions.GetOrDefault(typeof(TDbContext)); + if (actions == null) + { + ModelBuilderActions[typeof(TDbContext)] = actions = new List>(); + } + + actions.Add(new KeyValuePair(order, action)); + } public bool IsConfiguredDefault() { @@ -102,4 +163,4 @@ public class AbpDbContextOptions } } } -} +} \ No newline at end of file From 110180ed0fa489cc1191b0d7ff0423f0163fb2a5 Mon Sep 17 00:00:00 2001 From: Salih Date: Thu, 7 Mar 2024 13:44:32 +0300 Subject: [PATCH 2/7] Allow extending ConfigureConventions and OnModelCreating --- .../Abp/EntityFrameworkCore/AbpDbContext.cs | 43 +++++++++++++ .../AbpDbContextOptions.cs | 63 ++++++++++++++++++- 2 files changed, 105 insertions(+), 1 deletion(-) 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 b06ba191dd..72ec386cee 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs @@ -14,6 +14,7 @@ using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; using Volo.Abp.Auditing; using Volo.Abp.Data; using Volo.Abp.DependencyInjection; @@ -115,6 +116,48 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, .MakeGenericMethod(entityType.ClrType) .Invoke(this, new object[] { modelBuilder, entityType }); } + + var abpDbContextOptions = LazyServiceProvider.LazyGetRequiredService>().Value; + + var modelBuilderActions = abpDbContextOptions.ModelBuilderActions.Where(x => x.Key == typeof(TDbContext) || x.Key == typeof(AbpDbContext<>)).SelectMany(x => x.Value).ToList(); + + var actions = modelBuilderActions.OrderBy(a => a.Key).Select(a => a.Value).ToList(); + foreach (var action in actions) + { + if(action is Action modelBuilderAction) + { + modelBuilderAction.Invoke(modelBuilder, this); + } + + if(this is TDbContext dbContext && action is Action dbContextAction) + { + dbContextAction.Invoke(modelBuilder, dbContext); + } + } + } + + protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) + { + base.ConfigureConventions(configurationBuilder); + + var abpDbContextOptions = LazyServiceProvider.LazyGetRequiredService>().Value; + var conventions = abpDbContextOptions.Conventions.Where(x => x.Key == typeof(TDbContext) || x.Key == typeof(AbpDbContext<>)).SelectMany(x => x.Value).ToList(); + + + var actions = conventions.OrderBy(a => a.Key).Select(a => a.Value).ToList(); + + foreach (var action in actions) + { + if(action is Action modelBuilderAction) + { + modelBuilderAction.Invoke(configurationBuilder, this); + } + + if(this is TDbContext dbContext && action is Action dbContextAction) + { + dbContextAction.Invoke(configurationBuilder, dbContext); + } + } } protected virtual void TrySetDatabaseProvider(ModelBuilder modelBuilder) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs index cb5b258192..93de6a473c 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore; using Volo.Abp.DependencyInjection; using Volo.Abp.EntityFrameworkCore.DependencyInjection; using Volo.Abp.MultiTenancy; @@ -20,12 +21,18 @@ public class AbpDbContextOptions internal Dictionary DbContextReplacements { get; } + internal Dictionary>> Conventions { get; } + + internal Dictionary>> ModelBuilderActions { get; } + public AbpDbContextOptions() { DefaultPreConfigureActions = new List>(); PreConfigureActions = new Dictionary>(); ConfigureActions = new Dictionary(); DbContextReplacements = new Dictionary(); + Conventions = new Dictionary>>(); + ModelBuilderActions = new Dictionary>>(); } public void PreConfigure([NotNull] Action action) @@ -41,6 +48,60 @@ public class AbpDbContextOptions DefaultConfigureAction = action; } + + public void ConfigureConventions([NotNull] Action action, Type? dbContextType = null, int? order = null) + { + Check.NotNull(action, nameof(action)); + + var actions = Conventions.GetOrDefault(dbContextType ?? typeof(AbpDbContext<>)); + if (actions == null) + { + Conventions[dbContextType ?? typeof(AbpDbContext<>)] = actions = new List>(); + } + + actions.Add(new KeyValuePair(order, action)); + } + + public void ConfigureConventions([NotNull] Action action, int? order = null) + where TDbContext : AbpDbContext + { + Check.NotNull(action, nameof(action)); + + var actions = Conventions.GetOrDefault(typeof(TDbContext)); + if (actions == null) + { + Conventions[typeof(TDbContext)] = actions = new List>(); + } + + actions.Add(new KeyValuePair(order, action)); + } + + public void OnModelCreating([NotNull] Action action, Type? dbContextType = null, int? order = null) + { + Check.NotNull(action, nameof(action)); + + var actions = ModelBuilderActions.GetOrDefault(dbContextType ?? typeof(AbpDbContext<>)); + if (actions == null) + { + ModelBuilderActions[dbContextType ?? typeof(AbpDbContext<>)] = actions = new List>(); + } + + actions.Add(new KeyValuePair(order, action)); + } + + public void OnModelCreating([NotNull] Action action, int? order = null) + where TDbContext : AbpDbContext + { + Check.NotNull(action, nameof(action)); + + var actions = ModelBuilderActions.GetOrDefault(typeof(TDbContext)); + if (actions == null) + { + ModelBuilderActions[typeof(TDbContext)] = actions = new List>(); + } + + actions.Add(new KeyValuePair(order, action)); + } public bool IsConfiguredDefault() { @@ -102,4 +163,4 @@ public class AbpDbContextOptions } } } -} +} \ No newline at end of file From c1d49e47b3d57110cc7b46b3ba62c57f0c5059a2 Mon Sep 17 00:00:00 2001 From: Salih Date: Thu, 7 Mar 2024 14:16:25 +0300 Subject: [PATCH 3/7] Allow extending ConfigureConventions and OnModelCreating --- .../Abp/EntityFrameworkCore/AbpDbContext.cs | 19 ++++-- .../AbpDbContextOptions.cs | 66 +++++++++---------- 2 files changed, 43 insertions(+), 42 deletions(-) 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 edb4e77064..b0674b0be0 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs @@ -118,10 +118,14 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, } var abpDbContextOptions = LazyServiceProvider.LazyGetRequiredService>().Value; + + var actions = abpDbContextOptions.ModelBuilderActions + .Where(x => x.Key == typeof(TDbContext) || x.Key == typeof(AbpDbContext<>)) + .SelectMany(x => x.Value) + .OrderBy(a => a.Key) + .Select(a => a.Value) + .ToList(); - var modelBuilderActions = abpDbContextOptions.ModelBuilderActions.Where(x => x.Key == typeof(TDbContext) || x.Key == typeof(AbpDbContext<>)).SelectMany(x => x.Value).ToList(); - - var actions = modelBuilderActions.OrderBy(a => a.Key).Select(a => a.Value).ToList(); foreach (var action in actions) { if(action is Action modelBuilderAction) @@ -142,9 +146,12 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, var abpDbContextOptions = LazyServiceProvider.LazyGetRequiredService>().Value; - var conventions = abpDbContextOptions.Conventions.Where(x => x.Key == typeof(TDbContext) || x.Key == typeof(AbpDbContext<>)).SelectMany(x => x.Value).ToList(); - - var actions = conventions.OrderBy(a => a.Key).Select(a => a.Value).ToList(); + var actions = abpDbContextOptions.Conventions + .Where(x => x.Key == typeof(TDbContext) || x.Key == typeof(AbpDbContext<>)) + .SelectMany(x => x.Value) + .OrderBy(a => a.Key) + .Select(a => a.Value) + .ToList(); foreach (var action in actions) { diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs index 93de6a473c..f40974cdce 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs @@ -51,56 +51,24 @@ public class AbpDbContextOptions public void ConfigureConventions([NotNull] Action action, Type? dbContextType = null, int? order = null) { - Check.NotNull(action, nameof(action)); - - var actions = Conventions.GetOrDefault(dbContextType ?? typeof(AbpDbContext<>)); - if (actions == null) - { - Conventions[dbContextType ?? typeof(AbpDbContext<>)] = actions = new List>(); - } - - actions.Add(new KeyValuePair(order, action)); + InternalConfigureConventions(action, dbContextType, order); } public void ConfigureConventions([NotNull] Action action, int? order = null) where TDbContext : AbpDbContext { - Check.NotNull(action, nameof(action)); - - var actions = Conventions.GetOrDefault(typeof(TDbContext)); - if (actions == null) - { - Conventions[typeof(TDbContext)] = actions = new List>(); - } - - actions.Add(new KeyValuePair(order, action)); + InternalConfigureConventions(action, typeof(TDbContext), order); } public void OnModelCreating([NotNull] Action action, Type? dbContextType = null, int? order = null) { - Check.NotNull(action, nameof(action)); - - var actions = ModelBuilderActions.GetOrDefault(dbContextType ?? typeof(AbpDbContext<>)); - if (actions == null) - { - ModelBuilderActions[dbContextType ?? typeof(AbpDbContext<>)] = actions = new List>(); - } - - actions.Add(new KeyValuePair(order, action)); + InternalOnModelCreating(action, dbContextType, order); } public void OnModelCreating([NotNull] Action action, int? order = null) where TDbContext : AbpDbContext { - Check.NotNull(action, nameof(action)); - - var actions = ModelBuilderActions.GetOrDefault(typeof(TDbContext)); - if (actions == null) - { - ModelBuilderActions[typeof(TDbContext)] = actions = new List>(); - } - - actions.Add(new KeyValuePair(order, action)); + InternalOnModelCreating(action, typeof(TDbContext), order); } public bool IsConfiguredDefault() @@ -163,4 +131,30 @@ public class AbpDbContextOptions } } } + + private void InternalConfigureConventions(object action, Type? dbContextType = null, int? order = null) + { + Check.NotNull(action, nameof(action)); + + var actions = Conventions.GetOrDefault(dbContextType ?? typeof(AbpDbContext<>)); + if (actions == null) + { + Conventions[dbContextType ?? typeof(AbpDbContext<>)] = actions = new List>(); + } + + actions.Add(new KeyValuePair(order, action)); + } + + private void InternalOnModelCreating(object action, Type? dbContextType = null, int? order = null) + { + Check.NotNull(action, nameof(action)); + + var actions = ModelBuilderActions.GetOrDefault(dbContextType ?? typeof(AbpDbContext<>)); + if (actions == null) + { + ModelBuilderActions[dbContextType ?? typeof(AbpDbContext<>)] = actions = new List>(); + } + + actions.Add(new KeyValuePair(order, action)); + } } \ No newline at end of file From 1761019ca798f4fc96a85e3ab66ccc4612831c7c Mon Sep 17 00:00:00 2001 From: Salih Date: Thu, 7 Mar 2024 17:27:42 +0300 Subject: [PATCH 4/7] Fix test --- .../Volo/Abp/EntityFrameworkCore/AbpDbContext.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) 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 b0674b0be0..ef3e3b443c 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs @@ -116,7 +116,11 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, .MakeGenericMethod(entityType.ClrType) .Invoke(this, new object[] { modelBuilder, entityType }); } - + + if (LazyServiceProvider is null) + { + return; + } var abpDbContextOptions = LazyServiceProvider.LazyGetRequiredService>().Value; var actions = abpDbContextOptions.ModelBuilderActions @@ -144,6 +148,11 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, { base.ConfigureConventions(configurationBuilder); + if (LazyServiceProvider is null) + { + return; + } + var abpDbContextOptions = LazyServiceProvider.LazyGetRequiredService>().Value; var actions = abpDbContextOptions.Conventions From 98e64b896bbf9d824e86b3181e644934632d5a76 Mon Sep 17 00:00:00 2001 From: maliming Date: Fri, 8 Mar 2024 11:27:31 +0800 Subject: [PATCH 5/7] Update `AbpDbContextOptions`. --- .../Abp/EntityFrameworkCore/AbpDbContext.cs | 59 ++++-------- .../AbpDbContextOptions.cs | 92 ++++++++++--------- 2 files changed, 67 insertions(+), 84 deletions(-) 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 ef3e3b443c..e67280334c 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs @@ -117,29 +117,18 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, .Invoke(this, new object[] { modelBuilder, entityType }); } - if (LazyServiceProvider is null) + var abpDbContextOptions = LazyServiceProvider?.LazyGetRequiredService>().Value; + if (abpDbContextOptions != null) { - return; - } - var abpDbContextOptions = LazyServiceProvider.LazyGetRequiredService>().Value; + abpDbContextOptions.DefaultOnModelCreatingAction?.Invoke(this, modelBuilder); - var actions = abpDbContextOptions.ModelBuilderActions - .Where(x => x.Key == typeof(TDbContext) || x.Key == typeof(AbpDbContext<>)) - .SelectMany(x => x.Value) - .OrderBy(a => a.Key) - .Select(a => a.Value) - .ToList(); - - foreach (var action in actions) - { - if(action is Action modelBuilderAction) + var onModelCreatingActions = abpDbContextOptions.OnModelCreatingActions.GetOrDefault(typeof(TDbContext)); + if (!onModelCreatingActions.IsNullOrEmpty()) { - modelBuilderAction.Invoke(modelBuilder, this); - } - - if(this is TDbContext dbContext && action is Action dbContextAction) - { - dbContextAction.Invoke(modelBuilder, dbContext); + foreach (var onModelCreatingAction in onModelCreatingActions!) + { + onModelCreatingAction.As>().Invoke(this, modelBuilder); + } } } } @@ -148,30 +137,18 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, { base.ConfigureConventions(configurationBuilder); - if (LazyServiceProvider is null) + var abpDbContextOptions = LazyServiceProvider?.LazyGetRequiredService>().Value; + if (abpDbContextOptions != null) { - return; - } - - var abpDbContextOptions = LazyServiceProvider.LazyGetRequiredService>().Value; + abpDbContextOptions.DefaultConventionAction?.Invoke(this, configurationBuilder); - var actions = abpDbContextOptions.Conventions - .Where(x => x.Key == typeof(TDbContext) || x.Key == typeof(AbpDbContext<>)) - .SelectMany(x => x.Value) - .OrderBy(a => a.Key) - .Select(a => a.Value) - .ToList(); - - foreach (var action in actions) - { - if(action is Action modelBuilderAction) + var conventionActions = abpDbContextOptions.ConventionActions.GetOrDefault(typeof(TDbContext)); + if (!conventionActions.IsNullOrEmpty()) { - modelBuilderAction.Invoke(configurationBuilder, this); - } - - if(this is TDbContext dbContext && action is Action dbContextAction) - { - dbContextAction.Invoke(configurationBuilder, dbContext); + foreach (var conventionAction in conventionActions!) + { + conventionAction.As>().Invoke(this, configurationBuilder); + } } } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs index f40974cdce..acde97340b 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContextOptions.cs @@ -21,9 +21,13 @@ public class AbpDbContextOptions internal Dictionary DbContextReplacements { get; } - internal Dictionary>> Conventions { get; } - - internal Dictionary>> ModelBuilderActions { get; } + internal Action? DefaultConventionAction { get; set; } + + internal Dictionary> ConventionActions { get; } + + internal Action? DefaultOnModelCreatingAction { get; set; } + + internal Dictionary> OnModelCreatingActions { get; } public AbpDbContextOptions() { @@ -31,8 +35,8 @@ public class AbpDbContextOptions PreConfigureActions = new Dictionary>(); ConfigureActions = new Dictionary(); DbContextReplacements = new Dictionary(); - Conventions = new Dictionary>>(); - ModelBuilderActions = new Dictionary>>(); + ConventionActions = new Dictionary>(); + OnModelCreatingActions = new Dictionary>(); } public void PreConfigure([NotNull] Action action) @@ -48,27 +52,55 @@ public class AbpDbContextOptions DefaultConfigureAction = action; } - - public void ConfigureConventions([NotNull] Action action, Type? dbContextType = null, int? order = null) + + public void ConfigureDefaultConvention([NotNull] Action action) { - InternalConfigureConventions(action, dbContextType, order); + Check.NotNull(action, nameof(action)); + + DefaultConventionAction = action; } - - public void ConfigureConventions([NotNull] Action action, int? order = null) + + public void ConfigureConventions([NotNull] Action action) where TDbContext : AbpDbContext { - InternalConfigureConventions(action, typeof(TDbContext), order); + Check.NotNull(action, nameof(action)); + + var actions = ConventionActions.GetOrDefault(typeof(TDbContext)); + if (actions == null) + { + ConventionActions[typeof(TDbContext)] = new List + { + new Action((dbContext, builder) => action((TDbContext)dbContext, builder)) + }; + return; + } + + actions.Add(action); } - public void OnModelCreating([NotNull] Action action, Type? dbContextType = null, int? order = null) + public void ConfigureDefaultOnModelCreating([NotNull] Action action) { - InternalOnModelCreating(action, dbContextType, order); + Check.NotNull(action, nameof(action)); + + DefaultOnModelCreatingAction = action; } - - public void OnModelCreating([NotNull] Action action, int? order = null) + + public void ConfigureOnModelCreating([NotNull] Action action) where TDbContext : AbpDbContext { - InternalOnModelCreating(action, typeof(TDbContext), order); + Check.NotNull(action, nameof(action)); + + var actions = OnModelCreatingActions.GetOrDefault(typeof(TDbContext)); + if (actions == null) + { + OnModelCreatingActions[typeof(TDbContext)] = new List + { + new Action((dbContext, builder) => action((TDbContext)dbContext, builder)) + }; + return; + } + + actions.Add(action); } public bool IsConfiguredDefault() @@ -131,30 +163,4 @@ public class AbpDbContextOptions } } } - - private void InternalConfigureConventions(object action, Type? dbContextType = null, int? order = null) - { - Check.NotNull(action, nameof(action)); - - var actions = Conventions.GetOrDefault(dbContextType ?? typeof(AbpDbContext<>)); - if (actions == null) - { - Conventions[dbContextType ?? typeof(AbpDbContext<>)] = actions = new List>(); - } - - actions.Add(new KeyValuePair(order, action)); - } - - private void InternalOnModelCreating(object action, Type? dbContextType = null, int? order = null) - { - Check.NotNull(action, nameof(action)); - - var actions = ModelBuilderActions.GetOrDefault(dbContextType ?? typeof(AbpDbContext<>)); - if (actions == null) - { - ModelBuilderActions[dbContextType ?? typeof(AbpDbContext<>)] = actions = new List>(); - } - - actions.Add(new KeyValuePair(order, action)); - } -} \ No newline at end of file +} From 71311ee6b836294ddb0f206e595141d1f35656b6 Mon Sep 17 00:00:00 2001 From: maliming Date: Fri, 8 Mar 2024 12:42:46 +0800 Subject: [PATCH 6/7] Update AbpDbContext.cs --- .../Abp/EntityFrameworkCore/AbpDbContext.cs | 38 ++++++++----------- 1 file changed, 16 insertions(+), 22 deletions(-) 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 e67280334c..6c3ab12572 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs @@ -70,6 +70,8 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, public ILogger> Logger => LazyServiceProvider.LazyGetService>>(NullLogger>.Instance); + public IOptions Options => LazyServiceProvider.LazyGetRequiredService>(); + private static readonly MethodInfo ConfigureBasePropertiesMethodInfo = typeof(AbpDbContext) .GetMethod( @@ -117,19 +119,15 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, .Invoke(this, new object[] { modelBuilder, entityType }); } - var abpDbContextOptions = LazyServiceProvider?.LazyGetRequiredService>().Value; - if (abpDbContextOptions != null) + if (LazyServiceProvider == null || Options == null) { - abpDbContextOptions.DefaultOnModelCreatingAction?.Invoke(this, modelBuilder); + return; + } - var onModelCreatingActions = abpDbContextOptions.OnModelCreatingActions.GetOrDefault(typeof(TDbContext)); - if (!onModelCreatingActions.IsNullOrEmpty()) - { - foreach (var onModelCreatingAction in onModelCreatingActions!) - { - onModelCreatingAction.As>().Invoke(this, modelBuilder); - } - } + Options.Value.DefaultOnModelCreatingAction?.Invoke(this, modelBuilder); + foreach (var onModelCreatingAction in Options.Value.OnModelCreatingActions.GetOrDefault(typeof(TDbContext)) ?? []) + { + onModelCreatingAction.As>().Invoke(this, modelBuilder); } } @@ -137,19 +135,15 @@ public abstract class AbpDbContext : DbContext, IAbpEfCoreDbContext, { base.ConfigureConventions(configurationBuilder); - var abpDbContextOptions = LazyServiceProvider?.LazyGetRequiredService>().Value; - if (abpDbContextOptions != null) + if (LazyServiceProvider == null || Options == null) { - abpDbContextOptions.DefaultConventionAction?.Invoke(this, configurationBuilder); + return; + } - var conventionActions = abpDbContextOptions.ConventionActions.GetOrDefault(typeof(TDbContext)); - if (!conventionActions.IsNullOrEmpty()) - { - foreach (var conventionAction in conventionActions!) - { - conventionAction.As>().Invoke(this, configurationBuilder); - } - } + Options.Value.DefaultConventionAction?.Invoke(this, configurationBuilder); + foreach (var conventionAction in Options.Value.ConventionActions.GetOrDefault(typeof(TDbContext)) ?? []) + { + conventionAction.As>().Invoke(this, configurationBuilder); } } From 60be507d54bc4191806624157fa2035292dc899e Mon Sep 17 00:00:00 2001 From: maliming Date: Fri, 8 Mar 2024 16:39:06 +0800 Subject: [PATCH 7/7] Update Entity-Framework-Core.md --- docs/en/Entity-Framework-Core.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/docs/en/Entity-Framework-Core.md b/docs/en/Entity-Framework-Core.md index cb9393b1aa..73efe7970a 100644 --- a/docs/en/Entity-Framework-Core.md +++ b/docs/en/Entity-Framework-Core.md @@ -139,6 +139,30 @@ Configure(options => }); ```` +Add actions for the `ConfigureConventions` and `OnModelCreating` methods of the `DbContext` as shown below: + +````csharp +options.DefaultConventionAction = (dbContext, builder) => +{ + // This action is called for ConfigureConventions method of all DbContexts. +}; + +options.ConfigureConventions((dbContext, builder) => +{ + // This action is called for ConfigureConventions method of specific DbContext. +}); + +options.DefaultOnModelCreatingAction = (dbContext, builder) => +{ + // This action is called for OnModelCreating method of all DbContexts. +}; + +options.ConfigureOnModelCreating((dbContext, builder) => +{ + // This action is called for OnModelCreating method of specific DbContext. +}); +```` + If you have a single `DbContext` or you have multiple `DbContext`s but want to use the same DBMS and configuration for all, you can leave it as is. However, if you need to configure a different DBMS or customize the configuration for a specific `DbContext`, you can specify it as shown below: ````csharp