From f39543add6890b19db0cab18a0b326e5c8cfcd25 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Wed, 5 May 2021 14:46:43 +0800 Subject: [PATCH 1/6] Introduce ReplaceDbContextAttribute --- framework/Volo.Abp.sln | 7 +++ .../ReplaceDbContextAttribute.cs | 14 ++++++ .../AbpEntityFrameworkCoreModule.cs | 7 +++ .../AbpDbContextConventionalRegistrar.cs | 37 +++++++++++++++ .../AbpMongoDbConventionalRegistrar.cs | 23 ++++++++++ .../TestApp/FourthContext/FourthDbContext.cs | 17 +++++++ .../FourthDbContextDummyEntity.cs | 10 +++++ .../TestApp/FourthContext/IFourthDbContext.cs | 9 ++++ .../AbpEfCoreTestSecondContextModule.cs | 8 +++- .../AbpEntityFrameworkCoreTestModule.cs | 4 +- .../DbContext_Replace_Tests.cs | 21 +++++++-- .../EntityFrameworkCore/TestAppDbContext.cs | 13 ++++-- ...olo.Abp.MongoDB.Tests.SecondContext.csproj | 19 ++++++++ .../TestApp/FourthContext/FourthDbContext.cs | 13 ++++++ .../FourthDbContextDummyEntity.cs | 10 +++++ .../TestApp/FourthContext/IFourthDbContext.cs | 10 +++++ .../AbpMongoDbTestSecondContextModule.cs | 45 +++++++++++++++++++ .../SecondContext/BookInSecondDbContext.cs | 21 +++++++++ .../SecondContext/PhoneInSecondDbContext.cs | 18 ++++++++ .../SecondContextTestDataBuilder.cs | 30 +++++++++++++ .../TestApp/SecondContext/SecondDbContext.cs | 11 +++++ .../TestApp/ThirdDbContext/IThirdDbContext.cs | 9 ++++ .../TestApp/ThirdDbContext/ThirdDbContext.cs | 11 +++++ .../ThirdDbContextDummyEntity.cs | 10 +++++ .../Volo.Abp.MongoDB.Tests.csproj | 2 +- .../Volo/Abp/MongoDB/AbpMongoDbTestModule.cs | 13 +++--- .../Abp/MongoDB/DbContext_Replace_Tests.cs | 31 +++++++++++++ .../TestApp/MongoDb/TestAppMongoDbContext.cs | 11 ++++- 28 files changed, 415 insertions(+), 19 deletions(-) create mode 100644 framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/ReplaceDbContextAttribute.cs create mode 100644 framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DependencyInjection/AbpDbContextConventionalRegistrar.cs create mode 100644 framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/FourthContext/FourthDbContext.cs create mode 100644 framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/FourthContext/FourthDbContextDummyEntity.cs create mode 100644 framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/FourthContext/IFourthDbContext.cs create mode 100644 framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo.Abp.MongoDB.Tests.SecondContext.csproj create mode 100644 framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/FourthContext/FourthDbContext.cs create mode 100644 framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/FourthContext/FourthDbContextDummyEntity.cs create mode 100644 framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/FourthContext/IFourthDbContext.cs create mode 100644 framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/AbpMongoDbTestSecondContextModule.cs create mode 100644 framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/BookInSecondDbContext.cs create mode 100644 framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/PhoneInSecondDbContext.cs create mode 100644 framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/SecondContextTestDataBuilder.cs create mode 100644 framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/SecondDbContext.cs create mode 100644 framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/ThirdDbContext/IThirdDbContext.cs create mode 100644 framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/ThirdDbContext/ThirdDbContext.cs create mode 100644 framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/ThirdDbContext/ThirdDbContextDummyEntity.cs create mode 100644 framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DbContext_Replace_Tests.cs diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln index 160918667d..b71288ab93 100644 --- a/framework/Volo.Abp.sln +++ b/framework/Volo.Abp.sln @@ -395,6 +395,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.TextTemplating.Raz EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.TextTemplating.Scriban.Tests", "test\Volo.Abp.TextTemplating.Scriban.Tests\Volo.Abp.TextTemplating.Scriban.Tests.csproj", "{75D8DADB-3FA9-4C1D-B23A-DBFD08133B7C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.MongoDB.Tests.SecondContext", "test\Volo.Abp.MongoDB.Tests.SecondContext\Volo.Abp.MongoDB.Tests.SecondContext.csproj", "{90B1866A-EF99-40B9-970E-B898E5AA523F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1177,6 +1179,10 @@ Global {75D8DADB-3FA9-4C1D-B23A-DBFD08133B7C}.Debug|Any CPU.Build.0 = Debug|Any CPU {75D8DADB-3FA9-4C1D-B23A-DBFD08133B7C}.Release|Any CPU.ActiveCfg = Release|Any CPU {75D8DADB-3FA9-4C1D-B23A-DBFD08133B7C}.Release|Any CPU.Build.0 = Release|Any CPU + {90B1866A-EF99-40B9-970E-B898E5AA523F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {90B1866A-EF99-40B9-970E-B898E5AA523F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {90B1866A-EF99-40B9-970E-B898E5AA523F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {90B1866A-EF99-40B9-970E-B898E5AA523F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1376,6 +1382,7 @@ Global {42EA6F06-2D78-4D18-8AC4-8F2AB7E6DA19} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {C996F458-98FB-483D-9306-4701290E2FC1} = {447C8A77-E5F0-4538-8687-7383196D04EA} {75D8DADB-3FA9-4C1D-B23A-DBFD08133B7C} = {447C8A77-E5F0-4538-8687-7383196D04EA} + {90B1866A-EF99-40B9-970E-B898E5AA523F} = {447C8A77-E5F0-4538-8687-7383196D04EA} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/ReplaceDbContextAttribute.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/ReplaceDbContextAttribute.cs new file mode 100644 index 0000000000..7c3b280803 --- /dev/null +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/ReplaceDbContextAttribute.cs @@ -0,0 +1,14 @@ +using System; + +namespace Volo.Abp.DependencyInjection +{ + public class ReplaceDbContextAttribute : Attribute + { + public Type[] ReplacedDbContextTypes { get; } + + public ReplaceDbContextAttribute(params Type[] replacedDbContextTypes) + { + ReplacedDbContextTypes = replacedDbContextTypes; + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs index e92c8d35fa..3d03698443 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs @@ -1,6 +1,8 @@ using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.Domain; +using Volo.Abp.EntityFrameworkCore.DependencyInjection; using Volo.Abp.Modularity; using Volo.Abp.Uow.EntityFrameworkCore; @@ -9,6 +11,11 @@ namespace Volo.Abp.EntityFrameworkCore [DependsOn(typeof(AbpDddDomainModule))] public class AbpEntityFrameworkCoreModule : AbpModule { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddConventionalRegistrar(new AbpDbContextConventionalRegistrar()); + } + public override void ConfigureServices(ServiceConfigurationContext context) { Configure(options => diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DependencyInjection/AbpDbContextConventionalRegistrar.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DependencyInjection/AbpDbContextConventionalRegistrar.cs new file mode 100644 index 0000000000..d9d6214895 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DependencyInjection/AbpDbContextConventionalRegistrar.cs @@ -0,0 +1,37 @@ +using System; +using System.Reflection; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.EntityFrameworkCore.DependencyInjection +{ + public class AbpDbContextConventionalRegistrar : DefaultConventionalRegistrar + { + public override void AddType(IServiceCollection services, Type type) + { + if (!typeof(IAbpEfCoreDbContext).IsAssignableFrom(type) || type == typeof(AbpDbContext<>)) + { + return; + } + + var replaceDbContextAttribute = type.GetCustomAttribute(true); + if (replaceDbContextAttribute == null) + { + return; + } + + foreach (var dbContextType in replaceDbContextAttribute.ReplacedDbContextTypes) + { + services.Replace( + ServiceDescriptor.Transient( + dbContextType, + sp => sp.GetRequiredService(type) + ) + ); + + services.Configure(opts => { opts.DbContextReplacements[dbContextType] = type; }); + } + } + } +} diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DependencyInjection/AbpMongoDbConventionalRegistrar.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DependencyInjection/AbpMongoDbConventionalRegistrar.cs index cb1ed7ea54..8e8a0e39aa 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DependencyInjection/AbpMongoDbConventionalRegistrar.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DependencyInjection/AbpMongoDbConventionalRegistrar.cs @@ -1,5 +1,7 @@ using System; +using System.Reflection; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.DependencyInjection; namespace Volo.Abp.MongoDB.DependencyInjection @@ -22,6 +24,27 @@ namespace Volo.Abp.MongoDB.DependencyInjection } services.Add(ServiceDescriptor.Describe(typeof(IAbpMongoDbContext), type, ServiceLifetime.Transient)); + + var replaceDbContextAttribute = type.GetCustomAttribute(true); + if (replaceDbContextAttribute == null) + { + return; + } + + foreach (var dbContextType in replaceDbContextAttribute.ReplacedDbContextTypes) + { + services.Replace( + ServiceDescriptor.Transient( + dbContextType, + sp => sp.GetRequiredService(type) + ) + ); + + services.Configure(opts => + { + opts.DbContextReplacements[dbContextType] = type; + }); + } } } } diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/FourthContext/FourthDbContext.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/FourthContext/FourthDbContext.cs new file mode 100644 index 0000000000..5fa8a80367 --- /dev/null +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/FourthContext/FourthDbContext.cs @@ -0,0 +1,17 @@ +using Microsoft.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.TestApp.ThirdDbContext; + +namespace Volo.Abp.EntityFrameworkCore.TestApp.FourthContext +{ + /* This dbcontext is just for testing to replace dbcontext from the application using ReplaceDbContextAttribute + */ + public class FourthDbContext : AbpDbContext, IFourthDbContext + { + public DbSet FourthDummyEntities { get; set; } + + public FourthDbContext(DbContextOptions options) + : base(options) + { + } + } +} diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/FourthContext/FourthDbContextDummyEntity.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/FourthContext/FourthDbContextDummyEntity.cs new file mode 100644 index 0000000000..8043301215 --- /dev/null +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/FourthContext/FourthDbContextDummyEntity.cs @@ -0,0 +1,10 @@ +using System; +using Volo.Abp.Domain.Entities; + +namespace Volo.Abp.EntityFrameworkCore.TestApp.FourthContext +{ + public class FourthDbContextDummyEntity : AggregateRoot + { + public string Value { get; set; } + } +} diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/FourthContext/IFourthDbContext.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/FourthContext/IFourthDbContext.cs new file mode 100644 index 0000000000..eb2380d681 --- /dev/null +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/FourthContext/IFourthDbContext.cs @@ -0,0 +1,9 @@ +using Microsoft.EntityFrameworkCore; + +namespace Volo.Abp.EntityFrameworkCore.TestApp.FourthContext +{ + public interface IFourthDbContext : IEfCoreDbContext + { + DbSet FourthDummyEntities { get; set; } + } +} diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/SecondContext/AbpEfCoreTestSecondContextModule.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/SecondContext/AbpEfCoreTestSecondContextModule.cs index 80ece93c07..e5e02efa3b 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/SecondContext/AbpEfCoreTestSecondContextModule.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests.SecondContext/Volo/Abp/EntityFrameworkCore/TestApp/SecondContext/AbpEfCoreTestSecondContextModule.cs @@ -1,4 +1,5 @@ using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.EntityFrameworkCore.TestApp.FourthContext; using Volo.Abp.EntityFrameworkCore.TestApp.ThirdDbContext; using Volo.Abp.Modularity; using Volo.Abp.Threading; @@ -19,6 +20,11 @@ namespace Volo.Abp.EntityFrameworkCore.TestApp.SecondContext { options.AddDefaultRepositories(); }); + + context.Services.AddAbpDbContext(options => + { + options.AddDefaultRepositories(); + }); } public override void OnApplicationInitialization(ApplicationInitializationContext context) @@ -36,4 +42,4 @@ namespace Volo.Abp.EntityFrameworkCore.TestApp.SecondContext } } } -} \ No newline at end of file +} diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs index a1ca2e2846..4f8faef65e 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreTestModule.cs @@ -39,7 +39,7 @@ namespace Volo.Abp.EntityFrameworkCore { opt.DefaultWithDetailsFunc = q => q.Include(p => p.Phones); }); - + options.Entity(opt => { opt.DefaultWithDetailsFunc = q => q.Include(p => p.Books); @@ -76,7 +76,7 @@ namespace Volo.Abp.EntityFrameworkCore @"CREATE VIEW View_PersonView AS SELECT Name, CreationTime, Birthday, LastActive FROM People"); } - + return connection; } } diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DbContext_Replace_Tests.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DbContext_Replace_Tests.cs index 8fd88f23fe..4e343e7331 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DbContext_Replace_Tests.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DbContext_Replace_Tests.cs @@ -4,6 +4,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Shouldly; using Volo.Abp.Domain.Repositories; +using Volo.Abp.EntityFrameworkCore.TestApp.FourthContext; using Volo.Abp.EntityFrameworkCore.TestApp.ThirdDbContext; using Volo.Abp.TestApp.Domain; using Volo.Abp.TestApp.EntityFrameworkCore; @@ -15,13 +16,15 @@ namespace Volo.Abp.EntityFrameworkCore public class DbContext_Replace_Tests : EntityFrameworkCoreTestBase { private readonly IBasicRepository _dummyRepository; - private readonly IPersonRepository _personRepository; + private readonly IBasicRepository _fourthDummyRepository; + private readonly IPersonRepository _personRepository; private readonly IUnitOfWorkManager _unitOfWorkManager; private readonly AbpDbContextOptions _options; public DbContext_Replace_Tests() { _dummyRepository = GetRequiredService>(); + _fourthDummyRepository = GetRequiredService>(); _personRepository = GetRequiredService(); _unitOfWorkManager = GetRequiredService(); _options = GetRequiredService>().Value; @@ -31,8 +34,10 @@ namespace Volo.Abp.EntityFrameworkCore public async Task Should_Replace_DbContext() { _options.GetReplacedTypeOrSelf(typeof(IThirdDbContext)).ShouldBe(typeof(TestAppDbContext)); - + _options.GetReplacedTypeOrSelf(typeof(IFourthDbContext)).ShouldBe(typeof(TestAppDbContext)); + (ServiceProvider.GetRequiredService() is TestAppDbContext).ShouldBeTrue(); + (ServiceProvider.GetRequiredService() is TestAppDbContext).ShouldBeTrue(); using (var uow = _unitOfWorkManager.Begin()) { @@ -44,11 +49,19 @@ namespace Volo.Abp.EntityFrameworkCore var instance3 = await _personRepository.GetDbContextAsync(); (instance3 is TestAppDbContext).ShouldBeTrue(); - + + var instance4 = await _fourthDummyRepository.GetDbContextAsync(); + (instance4 is IFourthDbContext).ShouldBeTrue(); + + var instance5 = await _fourthDummyRepository.GetDbContextAsync(); + (instance5 is TestAppDbContext).ShouldBeTrue(); + // All instances should be the same! instance3.ShouldBe(instance1); instance3.ShouldBe(instance2); - + instance3.ShouldBe(instance4); + instance3.ShouldBe(instance5); + await uow.CompleteAsync(); } } diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs index da8bbc8a6c..cd8bb75b78 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/TestApp/EntityFrameworkCore/TestAppDbContext.cs @@ -1,12 +1,17 @@ using Microsoft.EntityFrameworkCore; +using Volo.Abp.DependencyInjection; using Volo.Abp.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore.TestApp.FourthContext; using Volo.Abp.EntityFrameworkCore.TestApp.ThirdDbContext; using Volo.Abp.TestApp.Domain; namespace Volo.Abp.TestApp.EntityFrameworkCore { - public class TestAppDbContext : AbpDbContext, IThirdDbContext + [ReplaceDbContext(typeof(IFourthDbContext))] + public class TestAppDbContext : AbpDbContext, IThirdDbContext, IFourthDbContext { + private DbSet _dummyEntities; + private DbSet _dummyEntities1; public DbSet People { get; set; } public DbSet Cities { get; set; } @@ -16,10 +21,12 @@ namespace Volo.Abp.TestApp.EntityFrameworkCore public DbSet DummyEntities { get; set; } public DbSet EntityWithIntPks { get; set; } - + public DbSet Author { get; set; } - public TestAppDbContext(DbContextOptions options) + public DbSet FourthDummyEntities { get; set; } + + public TestAppDbContext(DbContextOptions options) : base(options) { diff --git a/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo.Abp.MongoDB.Tests.SecondContext.csproj b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo.Abp.MongoDB.Tests.SecondContext.csproj new file mode 100644 index 0000000000..e779329ad7 --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo.Abp.MongoDB.Tests.SecondContext.csproj @@ -0,0 +1,19 @@ + + + + + + net5.0 + $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; + true + true + true + true + + + + + + + + diff --git a/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/FourthContext/FourthDbContext.cs b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/FourthContext/FourthDbContext.cs new file mode 100644 index 0000000000..7b496f954f --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/FourthContext/FourthDbContext.cs @@ -0,0 +1,13 @@ +using MongoDB.Driver; +using Volo.Abp.EntityFrameworkCore.TestApp.FourthContext; + +namespace Volo.Abp.MongoDB.TestApp.FourthContext +{ + /* This dbcontext is just for testing to replace dbcontext from the application using ReplaceDbContextAttribute + */ + public class FourthDbContext : AbpMongoDbContext, IFourthDbContext + { + public IMongoCollection FourthDummyEntities => Collection(); + + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/FourthContext/FourthDbContextDummyEntity.cs b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/FourthContext/FourthDbContextDummyEntity.cs new file mode 100644 index 0000000000..8043301215 --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/FourthContext/FourthDbContextDummyEntity.cs @@ -0,0 +1,10 @@ +using System; +using Volo.Abp.Domain.Entities; + +namespace Volo.Abp.EntityFrameworkCore.TestApp.FourthContext +{ + public class FourthDbContextDummyEntity : AggregateRoot + { + public string Value { get; set; } + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/FourthContext/IFourthDbContext.cs b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/FourthContext/IFourthDbContext.cs new file mode 100644 index 0000000000..ae9ee2f281 --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/FourthContext/IFourthDbContext.cs @@ -0,0 +1,10 @@ +using MongoDB.Driver; +using Volo.Abp.EntityFrameworkCore.TestApp.FourthContext; + +namespace Volo.Abp.MongoDB.TestApp.FourthContext +{ + public interface IFourthDbContext : IAbpMongoDbContext + { + IMongoCollection FourthDummyEntities { get;} + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/AbpMongoDbTestSecondContextModule.cs b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/AbpMongoDbTestSecondContextModule.cs new file mode 100644 index 0000000000..ba5eaf7f79 --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/AbpMongoDbTestSecondContextModule.cs @@ -0,0 +1,45 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Modularity; +using Volo.Abp.MongoDB.TestApp.FourthContext; +using Volo.Abp.MongoDB.TestApp.ThirdDbContext; +using Volo.Abp.Threading; + +namespace Volo.Abp.MongoDB.TestApp.SecondContext +{ + [DependsOn(typeof(AbpMongoDbModule))] + public class AbpMongoDbTestSecondContextModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddMongoDbContext(options => + { + options.AddDefaultRepositories(); + }); + + context.Services.AddMongoDbContext(options => + { + options.AddDefaultRepositories(); + }); + + context.Services.AddMongoDbContext(options => + { + options.AddDefaultRepositories(); + }); + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + SeedTestData(context); + } + + private static void SeedTestData(ApplicationInitializationContext context) + { + using (var scope = context.ServiceProvider.CreateScope()) + { + AsyncHelper.RunSync(() => scope.ServiceProvider + .GetRequiredService() + .BuildAsync()); + } + } + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/BookInSecondDbContext.cs b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/BookInSecondDbContext.cs new file mode 100644 index 0000000000..d7e81f4258 --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/BookInSecondDbContext.cs @@ -0,0 +1,21 @@ +using System; +using Volo.Abp.Domain.Entities; + +namespace Volo.Abp.MongoDB.TestApp.SecondContext +{ + public class BookInSecondDbContext : AggregateRoot + { + public string Name { get; set; } + + public BookInSecondDbContext() + { + + } + + public BookInSecondDbContext(Guid id, string name) + : base(id) + { + Name = name; + } + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/PhoneInSecondDbContext.cs b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/PhoneInSecondDbContext.cs new file mode 100644 index 0000000000..d808d5a52a --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/PhoneInSecondDbContext.cs @@ -0,0 +1,18 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; +using Volo.Abp.Domain.Entities; + +namespace Volo.Abp.MongoDB.TestApp.SecondContext +{ + public class PhoneInSecondDbContext : AggregateRoot + { + public virtual Guid PersonId { get; set; } + + public virtual string Number { get; set; } + + public override object[] GetKeys() + { + return new object[] {PersonId, Number}; + } + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/SecondContextTestDataBuilder.cs b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/SecondContextTestDataBuilder.cs new file mode 100644 index 0000000000..c3fb902c64 --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/SecondContextTestDataBuilder.cs @@ -0,0 +1,30 @@ +using System; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Guids; + +namespace Volo.Abp.MongoDB.TestApp.SecondContext +{ + public class SecondContextTestDataBuilder : ITransientDependency + { + private readonly IBasicRepository _bookRepository; + private readonly IGuidGenerator _guidGenerator; + + public SecondContextTestDataBuilder(IBasicRepository bookRepository, IGuidGenerator guidGenerator) + { + _bookRepository = bookRepository; + _guidGenerator = guidGenerator; + } + + public async Task BuildAsync() + { + await _bookRepository.InsertAsync( + new BookInSecondDbContext( + _guidGenerator.Create(), + "TestBook1" + ) + ); + } + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/SecondDbContext.cs b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/SecondDbContext.cs new file mode 100644 index 0000000000..2df5785b20 --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/SecondContext/SecondDbContext.cs @@ -0,0 +1,11 @@ +using MongoDB.Driver; + +namespace Volo.Abp.MongoDB.TestApp.SecondContext +{ + public class SecondDbContext : AbpMongoDbContext + { + public IMongoCollection Books => Collection(); + + public IMongoCollection Phones => Collection(); + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/ThirdDbContext/IThirdDbContext.cs b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/ThirdDbContext/IThirdDbContext.cs new file mode 100644 index 0000000000..cfe629b5a7 --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/ThirdDbContext/IThirdDbContext.cs @@ -0,0 +1,9 @@ +using MongoDB.Driver; + +namespace Volo.Abp.MongoDB.TestApp.ThirdDbContext +{ + public interface IThirdDbContext : IAbpMongoDbContext + { + IMongoCollection DummyEntities { get; } + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/ThirdDbContext/ThirdDbContext.cs b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/ThirdDbContext/ThirdDbContext.cs new file mode 100644 index 0000000000..c3b018a699 --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/ThirdDbContext/ThirdDbContext.cs @@ -0,0 +1,11 @@ +using MongoDB.Driver; + +namespace Volo.Abp.MongoDB.TestApp.ThirdDbContext +{ + /* This dbcontext is just for testing to replace dbcontext from the application using AbpDbContextRegistrationOptions.ReplaceDbContext + */ + public class ThirdDbContext : AbpMongoDbContext, IThirdDbContext + { + public IMongoCollection DummyEntities => Collection(); + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/ThirdDbContext/ThirdDbContextDummyEntity.cs b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/ThirdDbContext/ThirdDbContextDummyEntity.cs new file mode 100644 index 0000000000..a784406ff5 --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests.SecondContext/Volo/Abp/MongoDB/TestApp/ThirdDbContext/ThirdDbContextDummyEntity.cs @@ -0,0 +1,10 @@ +using System; +using Volo.Abp.Domain.Entities; + +namespace Volo.Abp.MongoDB.TestApp.ThirdDbContext +{ + public class ThirdDbContextDummyEntity : AggregateRoot + { + public string Value { get; set; } + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj b/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj index c36fbb799c..21bcac616e 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo.Abp.MongoDB.Tests.csproj @@ -9,8 +9,8 @@ - + diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/AbpMongoDbTestModule.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/AbpMongoDbTestModule.cs index e580c6fce6..100011560e 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/AbpMongoDbTestModule.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/AbpMongoDbTestModule.cs @@ -1,21 +1,18 @@ using System; -using System.Linq; -using System.Threading; using Microsoft.Extensions.DependencyInjection; -using MongoDB.Driver; -using MongoDB.Driver.Core.Servers; using Volo.Abp.Data; using Volo.Abp.Modularity; +using Volo.Abp.MongoDB.TestApp.SecondContext; +using Volo.Abp.MongoDB.TestApp.ThirdDbContext; using Volo.Abp.TestApp; using Volo.Abp.TestApp.Domain; using Volo.Abp.TestApp.MongoDB; -using Volo.Abp.Uow; namespace Volo.Abp.MongoDB { [DependsOn( - typeof(AbpMongoDbModule), - typeof(TestAppModule) + typeof(TestAppModule), + typeof(AbpMongoDbTestSecondContextModule) )] public class AbpMongoDbTestModule : AbpModule { @@ -35,6 +32,8 @@ namespace Volo.Abp.MongoDB { options.AddDefaultRepositories(); options.AddRepository(); + + options.ReplaceDbContext(); }); } } diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DbContext_Replace_Tests.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DbContext_Replace_Tests.cs new file mode 100644 index 0000000000..eefa6852bf --- /dev/null +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/MongoDB/DbContext_Replace_Tests.cs @@ -0,0 +1,31 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Shouldly; +using Volo.Abp.MongoDB.TestApp.FourthContext; +using Volo.Abp.MongoDB.TestApp.ThirdDbContext; +using Volo.Abp.TestApp.MongoDB; +using Xunit; + +namespace Volo.Abp.MongoDB +{ + [Collection(MongoTestCollection.Name)] + public class DbContext_Replace_Tests : MongoDbTestBase + { + private readonly AbpMongoDbContextOptions _options; + + public DbContext_Replace_Tests() + { + _options = GetRequiredService>().Value; + } + + [Fact] + public void Should_Replace_DbContext() + { + _options.GetReplacedTypeOrSelf(typeof(IThirdDbContext)).ShouldBe(typeof(TestAppMongoDbContext)); + _options.GetReplacedTypeOrSelf(typeof(IFourthDbContext)).ShouldBe(typeof(TestAppMongoDbContext)); + + (ServiceProvider.GetRequiredService() is TestAppMongoDbContext).ShouldBeTrue(); + (ServiceProvider.GetRequiredService() is TestAppMongoDbContext).ShouldBeTrue(); + } + } +} diff --git a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/TestAppMongoDbContext.cs b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/TestAppMongoDbContext.cs index eed8d4ade3..68a2856e01 100644 --- a/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/TestAppMongoDbContext.cs +++ b/framework/test/Volo.Abp.MongoDB.Tests/Volo/Abp/TestApp/MongoDb/TestAppMongoDbContext.cs @@ -1,12 +1,17 @@ using MongoDB.Driver; using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.EntityFrameworkCore.TestApp.FourthContext; using Volo.Abp.MongoDB; +using Volo.Abp.MongoDB.TestApp.FourthContext; +using Volo.Abp.MongoDB.TestApp.ThirdDbContext; using Volo.Abp.TestApp.Domain; namespace Volo.Abp.TestApp.MongoDB { [ConnectionStringName("TestApp")] - public class TestAppMongoDbContext : AbpMongoDbContext, ITestAppMongoDbContext + [ReplaceDbContext(typeof(IFourthDbContext))] + public class TestAppMongoDbContext : AbpMongoDbContext, ITestAppMongoDbContext, IThirdDbContext, IFourthDbContext { [MongoCollection("Persons")] //Intentionally changed the collection name to test it public IMongoCollection People => Collection(); @@ -15,6 +20,10 @@ namespace Volo.Abp.TestApp.MongoDB public IMongoCollection Cities => Collection(); + public IMongoCollection DummyEntities => Collection(); + + public IMongoCollection FourthDummyEntities => Collection(); + protected internal override void CreateModel(IMongoModelBuilder modelBuilder) { base.CreateModel(modelBuilder); From 6bd06f6f678093da1faa62068889a100c953b725 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Wed, 5 May 2021 15:08:52 +0800 Subject: [PATCH 2/6] Update document --- docs/en/Entity-Framework-Core.md | 14 +++++++++++++- docs/en/MongoDB.md | 14 +++++++++++++- docs/zh-Hans/Entity-Framework-Core.md | 14 +++++++++++++- docs/zh-Hans/MongoDB.md | 14 +++++++++++++- 4 files changed, 52 insertions(+), 4 deletions(-) diff --git a/docs/en/Entity-Framework-Core.md b/docs/en/Entity-Framework-Core.md index a2c0e79996..aced8d406d 100644 --- a/docs/en/Entity-Framework-Core.md +++ b/docs/en/Entity-Framework-Core.md @@ -706,7 +706,19 @@ One advantage of using an interface for a DbContext is then it will be replaceab ### Replace Other DbContextes -Once you properly define and use an interface for DbContext, then any other implementation can replace it using the `ReplaceDbContext` option: +Once you properly define and use an interface for DbContext, then any other implementation can use the following ways to replace it: + +**ReplaceDbContextAttribute** + +```csharp +[ReplaceDbContext(typeof(IBookStoreDbContext))] +public class OtherDbContext : AbpDbContext, IBookStoreDbContext +{ + //... +} +``` + +**ReplaceDbContext option** ````csharp context.Services.AddAbpDbContext(options => diff --git a/docs/en/MongoDB.md b/docs/en/MongoDB.md index a12d216b3d..ae8f5c82d1 100644 --- a/docs/en/MongoDB.md +++ b/docs/en/MongoDB.md @@ -373,7 +373,19 @@ One advantage of using interface for a MongoDbContext is then it becomes replace #### Replace Other DbContextes -Once you properly define and use an interface for a MongoDbContext , then any other implementation can replace it using the `ReplaceDbContext` option: +Once you properly define and use an interface for a MongoDbContext , then any other implementation can use the following ways to replace it: + +**ReplaceDbContextAttribute** + +```csharp +[ReplaceDbContext(typeof(IBookStoreMongoDbContext))] +public class OtherMongoDbContext : AbpMongoDbContext, IBookStoreMongoDbContext +{ + //... +} +``` + +**ReplaceDbContext option** ```csharp context.Services.AddMongoDbContext(options => diff --git a/docs/zh-Hans/Entity-Framework-Core.md b/docs/zh-Hans/Entity-Framework-Core.md index b5252b86c0..4139407f04 100644 --- a/docs/zh-Hans/Entity-Framework-Core.md +++ b/docs/zh-Hans/Entity-Framework-Core.md @@ -433,7 +433,19 @@ public class BookRepository : EfCoreRepository, ### 替换其他仓储 -正确定义并使用DbContext接口后,任何其他实现都可以使用以下ReplaceDbContext options 替换它: +正确定义并使用DbContext接口后,任何其他实现都可以使用以下方法替换它: + +**ReplaceDbContextAttribute** + +```csharp +[ReplaceDbContext(typeof(IBookStoreDbContext))] +public class OtherDbContext : AbpDbContext, IBookStoreDbContext +{ + //... +} +``` + +**ReplaceDbContext option** ````csharp context.Services.AddAbpDbContext(options => diff --git a/docs/zh-Hans/MongoDB.md b/docs/zh-Hans/MongoDB.md index af63642a41..87c99d3207 100644 --- a/docs/zh-Hans/MongoDB.md +++ b/docs/zh-Hans/MongoDB.md @@ -329,7 +329,19 @@ public class BookRepository ##### 替换其他的DbContexts -一旦你正确定义并为MongoDbContext使用了接口,其他的实现就可以使用`ReplaceDbContext`来替换: +一旦你正确定义并为MongoDbContext使用了接口,任何其他实现都可以使用以下方法替换它: + +**ReplaceDbContextAttribute** + +```csharp +[ReplaceDbContext(typeof(IBookStoreMongoDbContext))] +public class OtherMongoDbContext : AbpMongoDbContext, IBookStoreMongoDbContext +{ + //... +} +``` + +**ReplaceDbContext option** ```csharp context.Services.AddMongoDbContext(options => From adc3097dd7a91c897fb53155ed8a880cc2db0257 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Wed, 5 May 2021 16:22:53 +0800 Subject: [PATCH 3/6] Update ReplaceDbContextAttribute --- .../Volo/Abp/DependencyInjection/ReplaceDbContextAttribute.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/ReplaceDbContextAttribute.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/ReplaceDbContextAttribute.cs index 7c3b280803..708d3ff470 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/ReplaceDbContextAttribute.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/ReplaceDbContextAttribute.cs @@ -2,6 +2,7 @@ namespace Volo.Abp.DependencyInjection { + [AttributeUsage(AttributeTargets.Class)] public class ReplaceDbContextAttribute : Attribute { public Type[] ReplacedDbContextTypes { get; } From d13b6c8b0c9a2d9373f0db4a38c8b4369c943be1 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Fri, 7 May 2021 09:11:41 +0800 Subject: [PATCH 4/6] Improved --- .../AbpEfCoreServiceCollectionExtensions.cs | 10 ++++- .../AbpEntityFrameworkCoreModule.cs | 5 --- .../AbpDbContextConventionalRegistrar.cs | 37 ------------------- .../AbpMongoDbServiceCollectionExtensions.cs | 10 ++++- .../AbpMongoDbConventionalRegistrar.cs | 21 ----------- 5 files changed, 18 insertions(+), 65 deletions(-) delete mode 100644 framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DependencyInjection/AbpDbContextConventionalRegistrar.cs diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Microsoft/Extensions/DependencyInjection/AbpEfCoreServiceCollectionExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Microsoft/Extensions/DependencyInjection/AbpEfCoreServiceCollectionExtensions.cs index 538614ee22..07e86cb0e3 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Microsoft/Extensions/DependencyInjection/AbpEfCoreServiceCollectionExtensions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Microsoft/Extensions/DependencyInjection/AbpEfCoreServiceCollectionExtensions.cs @@ -1,5 +1,7 @@ using System; +using System.Reflection; using Microsoft.Extensions.DependencyInjection.Extensions; +using Volo.Abp.DependencyInjection; using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore.DependencyInjection; @@ -8,7 +10,7 @@ namespace Microsoft.Extensions.DependencyInjection public static class AbpEfCoreServiceCollectionExtensions { public static IServiceCollection AddAbpDbContext( - this IServiceCollection services, + this IServiceCollection services, Action optionsBuilder = null) where TDbContext : AbpDbContext { @@ -19,6 +21,12 @@ namespace Microsoft.Extensions.DependencyInjection services.TryAddTransient(DbContextOptionsFactory.Create); + var replaceDbContextAttribute = typeof(TDbContext).GetCustomAttribute(true); + if (replaceDbContextAttribute != null) + { + options.ReplacedDbContextTypes.AddRange(replaceDbContextAttribute.ReplacedDbContextTypes); + } + foreach (var dbContextType in options.ReplacedDbContextTypes) { services.Replace( diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs index 3d03698443..b5d9eb8436 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpEntityFrameworkCoreModule.cs @@ -11,11 +11,6 @@ namespace Volo.Abp.EntityFrameworkCore [DependsOn(typeof(AbpDddDomainModule))] public class AbpEntityFrameworkCoreModule : AbpModule { - public override void PreConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddConventionalRegistrar(new AbpDbContextConventionalRegistrar()); - } - public override void ConfigureServices(ServiceConfigurationContext context) { Configure(options => diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DependencyInjection/AbpDbContextConventionalRegistrar.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DependencyInjection/AbpDbContextConventionalRegistrar.cs deleted file mode 100644 index d9d6214895..0000000000 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/DependencyInjection/AbpDbContextConventionalRegistrar.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using System.Reflection; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Volo.Abp.DependencyInjection; - -namespace Volo.Abp.EntityFrameworkCore.DependencyInjection -{ - public class AbpDbContextConventionalRegistrar : DefaultConventionalRegistrar - { - public override void AddType(IServiceCollection services, Type type) - { - if (!typeof(IAbpEfCoreDbContext).IsAssignableFrom(type) || type == typeof(AbpDbContext<>)) - { - return; - } - - var replaceDbContextAttribute = type.GetCustomAttribute(true); - if (replaceDbContextAttribute == null) - { - return; - } - - foreach (var dbContextType in replaceDbContextAttribute.ReplacedDbContextTypes) - { - services.Replace( - ServiceDescriptor.Transient( - dbContextType, - sp => sp.GetRequiredService(type) - ) - ); - - services.Configure(opts => { opts.DbContextReplacements[dbContextType] = type; }); - } - } - } -} diff --git a/framework/src/Volo.Abp.MongoDB/Microsoft/Extensions/DependencyInjection/AbpMongoDbServiceCollectionExtensions.cs b/framework/src/Volo.Abp.MongoDB/Microsoft/Extensions/DependencyInjection/AbpMongoDbServiceCollectionExtensions.cs index 5adf7300ee..48e3115306 100644 --- a/framework/src/Volo.Abp.MongoDB/Microsoft/Extensions/DependencyInjection/AbpMongoDbServiceCollectionExtensions.cs +++ b/framework/src/Volo.Abp.MongoDB/Microsoft/Extensions/DependencyInjection/AbpMongoDbServiceCollectionExtensions.cs @@ -1,5 +1,7 @@ using System; +using System.Reflection; using Microsoft.Extensions.DependencyInjection.Extensions; +using Volo.Abp.DependencyInjection; using Volo.Abp.MongoDB; using Volo.Abp.MongoDB.DependencyInjection; @@ -13,11 +15,17 @@ namespace Microsoft.Extensions.DependencyInjection var options = new AbpMongoDbContextRegistrationOptions(typeof(TMongoDbContext), services); optionsBuilder?.Invoke(options); + var replaceDbContextAttribute = typeof(TMongoDbContext).GetCustomAttribute(true); + if (replaceDbContextAttribute != null) + { + options.ReplacedDbContextTypes.AddRange(replaceDbContextAttribute.ReplacedDbContextTypes); + } + foreach (var dbContextType in options.ReplacedDbContextTypes) { services.Replace(ServiceDescriptor.Transient(dbContextType, typeof(TMongoDbContext))); } - + foreach (var dbContextType in options.ReplacedDbContextTypes) { services.Replace( diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DependencyInjection/AbpMongoDbConventionalRegistrar.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DependencyInjection/AbpMongoDbConventionalRegistrar.cs index 8e8a0e39aa..e0a6265f7c 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DependencyInjection/AbpMongoDbConventionalRegistrar.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/DependencyInjection/AbpMongoDbConventionalRegistrar.cs @@ -24,27 +24,6 @@ namespace Volo.Abp.MongoDB.DependencyInjection } services.Add(ServiceDescriptor.Describe(typeof(IAbpMongoDbContext), type, ServiceLifetime.Transient)); - - var replaceDbContextAttribute = type.GetCustomAttribute(true); - if (replaceDbContextAttribute == null) - { - return; - } - - foreach (var dbContextType in replaceDbContextAttribute.ReplacedDbContextTypes) - { - services.Replace( - ServiceDescriptor.Transient( - dbContextType, - sp => sp.GetRequiredService(type) - ) - ); - - services.Configure(opts => - { - opts.DbContextReplacements[dbContextType] = type; - }); - } } } } From 2b0407d986f608c4f17a10c89d2400cd369810f1 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Fri, 7 May 2021 09:17:31 +0800 Subject: [PATCH 5/6] Get attribute before optionsBuilder?.Invoke(options); --- .../AbpEfCoreServiceCollectionExtensions.cs | 7 ++++--- .../AbpMongoDbServiceCollectionExtensions.cs | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Microsoft/Extensions/DependencyInjection/AbpEfCoreServiceCollectionExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Microsoft/Extensions/DependencyInjection/AbpEfCoreServiceCollectionExtensions.cs index 07e86cb0e3..956b2937aa 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Microsoft/Extensions/DependencyInjection/AbpEfCoreServiceCollectionExtensions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Microsoft/Extensions/DependencyInjection/AbpEfCoreServiceCollectionExtensions.cs @@ -17,9 +17,6 @@ namespace Microsoft.Extensions.DependencyInjection services.AddMemoryCache(); var options = new AbpDbContextRegistrationOptions(typeof(TDbContext), services); - optionsBuilder?.Invoke(options); - - services.TryAddTransient(DbContextOptionsFactory.Create); var replaceDbContextAttribute = typeof(TDbContext).GetCustomAttribute(true); if (replaceDbContextAttribute != null) @@ -27,6 +24,10 @@ namespace Microsoft.Extensions.DependencyInjection options.ReplacedDbContextTypes.AddRange(replaceDbContextAttribute.ReplacedDbContextTypes); } + optionsBuilder?.Invoke(options); + + services.TryAddTransient(DbContextOptionsFactory.Create); + foreach (var dbContextType in options.ReplacedDbContextTypes) { services.Replace( diff --git a/framework/src/Volo.Abp.MongoDB/Microsoft/Extensions/DependencyInjection/AbpMongoDbServiceCollectionExtensions.cs b/framework/src/Volo.Abp.MongoDB/Microsoft/Extensions/DependencyInjection/AbpMongoDbServiceCollectionExtensions.cs index 48e3115306..13131718c0 100644 --- a/framework/src/Volo.Abp.MongoDB/Microsoft/Extensions/DependencyInjection/AbpMongoDbServiceCollectionExtensions.cs +++ b/framework/src/Volo.Abp.MongoDB/Microsoft/Extensions/DependencyInjection/AbpMongoDbServiceCollectionExtensions.cs @@ -13,7 +13,6 @@ namespace Microsoft.Extensions.DependencyInjection where TMongoDbContext : AbpMongoDbContext { var options = new AbpMongoDbContextRegistrationOptions(typeof(TMongoDbContext), services); - optionsBuilder?.Invoke(options); var replaceDbContextAttribute = typeof(TMongoDbContext).GetCustomAttribute(true); if (replaceDbContextAttribute != null) @@ -21,6 +20,8 @@ namespace Microsoft.Extensions.DependencyInjection options.ReplacedDbContextTypes.AddRange(replaceDbContextAttribute.ReplacedDbContextTypes); } + optionsBuilder?.Invoke(options); + foreach (var dbContextType in options.ReplacedDbContextTypes) { services.Replace(ServiceDescriptor.Transient(dbContextType, typeof(TMongoDbContext))); From 33fcd398a8c67f6728d9ae4cbc9216f089ab3a68 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Tue, 11 May 2021 09:48:39 +0800 Subject: [PATCH 6/6] Support multiple usages of the attribute --- .../AbpCommonDbContextRegistrationOptions.cs | 6 +++--- .../Abp/DependencyInjection/ReplaceDbContextAttribute.cs | 2 +- .../AbpEfCoreServiceCollectionExtensions.cs | 9 ++++++--- .../AbpMongoDbServiceCollectionExtensions.cs | 9 ++++++--- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/AbpCommonDbContextRegistrationOptions.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/AbpCommonDbContextRegistrationOptions.cs index 6408e3f0fa..ee172b3409 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/AbpCommonDbContextRegistrationOptions.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/AbpCommonDbContextRegistrationOptions.cs @@ -55,7 +55,7 @@ namespace Volo.Abp.DependencyInjection throw new AbpException($"{OriginalDbContextType.AssemblyQualifiedName} should inherit/implement {otherDbContextType.AssemblyQualifiedName}!"); } - ReplacedDbContextTypes.Add(otherDbContextType); + ReplacedDbContextTypes.AddIfNotContains(otherDbContextType); return this; } @@ -93,9 +93,9 @@ namespace Volo.Abp.DependencyInjection public IAbpCommonDbContextRegistrationOptionsBuilder AddDefaultRepository(Type entityType) { EntityHelper.CheckEntity(entityType); - + SpecifiedDefaultRepositories.AddIfNotContains(entityType); - + return this; } diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/ReplaceDbContextAttribute.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/ReplaceDbContextAttribute.cs index 708d3ff470..625e6841a0 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/ReplaceDbContextAttribute.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/DependencyInjection/ReplaceDbContextAttribute.cs @@ -2,7 +2,7 @@ namespace Volo.Abp.DependencyInjection { - [AttributeUsage(AttributeTargets.Class)] + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] public class ReplaceDbContextAttribute : Attribute { public Type[] ReplacedDbContextTypes { get; } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Microsoft/Extensions/DependencyInjection/AbpEfCoreServiceCollectionExtensions.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Microsoft/Extensions/DependencyInjection/AbpEfCoreServiceCollectionExtensions.cs index 956b2937aa..a48575ddcc 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Microsoft/Extensions/DependencyInjection/AbpEfCoreServiceCollectionExtensions.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Microsoft/Extensions/DependencyInjection/AbpEfCoreServiceCollectionExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Reflection; using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.DependencyInjection; @@ -18,10 +19,12 @@ namespace Microsoft.Extensions.DependencyInjection var options = new AbpDbContextRegistrationOptions(typeof(TDbContext), services); - var replaceDbContextAttribute = typeof(TDbContext).GetCustomAttribute(true); - if (replaceDbContextAttribute != null) + var replacedDbContextTypes = typeof(TDbContext).GetCustomAttributes(true) + .SelectMany( x => x.ReplacedDbContextTypes).ToList(); + + foreach (var dbContextType in replacedDbContextTypes) { - options.ReplacedDbContextTypes.AddRange(replaceDbContextAttribute.ReplacedDbContextTypes); + options.ReplaceDbContext(dbContextType); } optionsBuilder?.Invoke(options); diff --git a/framework/src/Volo.Abp.MongoDB/Microsoft/Extensions/DependencyInjection/AbpMongoDbServiceCollectionExtensions.cs b/framework/src/Volo.Abp.MongoDB/Microsoft/Extensions/DependencyInjection/AbpMongoDbServiceCollectionExtensions.cs index 13131718c0..7f9c6b8d42 100644 --- a/framework/src/Volo.Abp.MongoDB/Microsoft/Extensions/DependencyInjection/AbpMongoDbServiceCollectionExtensions.cs +++ b/framework/src/Volo.Abp.MongoDB/Microsoft/Extensions/DependencyInjection/AbpMongoDbServiceCollectionExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Reflection; using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.DependencyInjection; @@ -14,10 +15,12 @@ namespace Microsoft.Extensions.DependencyInjection { var options = new AbpMongoDbContextRegistrationOptions(typeof(TMongoDbContext), services); - var replaceDbContextAttribute = typeof(TMongoDbContext).GetCustomAttribute(true); - if (replaceDbContextAttribute != null) + var replacedDbContextTypes = typeof(TMongoDbContext).GetCustomAttributes(true) + .SelectMany( x => x.ReplacedDbContextTypes).ToList(); + + foreach (var dbContextType in replacedDbContextTypes) { - options.ReplacedDbContextTypes.AddRange(replaceDbContextAttribute.ReplacedDbContextTypes); + options.ReplaceDbContext(dbContextType); } optionsBuilder?.Invoke(options);