Base solution for your next web application
Open Closed

Using Migrator tool to apply migration on multiple DB Context #8465


User avatar
0
adamphones created

Is there any way to apply migration to multiple db context by using Migrator tool? I don't mean for multi tenant applicaiton. In the application we disabled multi tenant but we have another dbcontext that we would like to apply migration through Migrator.

I would appriciate if you could point me right direction or anyone has this issue.

I have seen here Ismail suggested adding another tenant but I don't find this a good way as this requires storing connection string in database.


9 Answer(s)
  • User Avatar
    0
    maliming created
    Support Team

    hi

    Try injecting AbpZeroDbMigrator<SecondDbContext> in MultiTenantMigrateExecuter

  • User Avatar
    0
    adamphones created

    I tried this but the instance cannot be created with the following error. Not sure how I should register this in Migrator project.

    Message	"Can't create component 'Project.Migrator.MultiTenantMigrateExecuter' as it has dependencies to be satisfied.\r\n\r\n'Project.Migrator.MultiTenantMigrateExecuter' is waiting for the following dependencies:\r\n- Service 'Abp.Zero.EntityFrameworkCore.AbpZeroDbMigrator 1[[Project.EntityFrameworkCore.APLBillingDbContext, Project.EntityFrameworkCore, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' which was not registered.\r\n"	string
    

    I have followed the same pattern and created SecondDBMigrator class as below:

    public class SecondDBMigrator : AbpZeroDbMigrator<SecondDBContext>
            {
                public SecondDBMigrator(
                    IUnitOfWorkManager unitOfWorkManager,
                    IDbPerTenantConnectionStringResolver connectionStringResolver,
                    IDbContextResolver dbContextResolver) :
                    base(
                        unitOfWorkManager,
                        connectionStringResolver,
                        dbContextResolver)
                {
    
                }
            }
            ```
            
    With this I don't get exexption but when I look at instance of the migrator connection string in debug mode I see the default database connection string registered instead of second database.  
         
    
  • User Avatar
    0
    adamphones created

    Not sure what that would change but yeah it doesn't work either...

    I hope you get my point. The database connection still points to default db context connection.

  • User Avatar
    0
    maliming created
    Support Team

    hi adamphones

    I understand your situation now, I will provide you some code later, please wait. : )

  • User Avatar
    0
    adamphones created

    thanks :)

  • User Avatar
    0
    maliming created
    Support Team
    {
      "ConnectionStrings": {
        "Default": "Server=localhost; Database=AbpZeroTemplateDb; Trusted_Connection=True;",
        "Test": "Server=localhost; Database=Test; Trusted_Connection=True;"
      }
    }
    
    
    public class MyDbPerTenantConnectionStringResolver : DbPerTenantConnectionStringResolver
    {
    	private readonly IAppConfigurationAccessor _appConfigurationAccessor;
    
    	public MyDbPerTenantConnectionStringResolver(IAbpStartupConfiguration configuration,
    		ICurrentUnitOfWorkProvider currentUnitOfWorkProvider, ITenantCache tenantCache,
    		IAppConfigurationAccessor appConfigurationAccessor) : base(configuration,
    		currentUnitOfWorkProvider, tenantCache)
    	{
    		_appConfigurationAccessor = appConfigurationAccessor;
    	}
    
    	public override string GetNameOrConnectionString(DbPerTenantConnectionStringResolveArgs args)
    	{
    		if (args.ContainsKey("DbContextType") && args["DbContextType"] as Type == typeof(TestDbContext))
    		{
    			return _appConfigurationAccessor.Configuration["ConnectionStrings:Test"];
    		}
    
    		return base.GetNameOrConnectionString(args);
    	}
    }
    
    public override void PreInitialize()
    {
    	//...
    	Configuration.ReplaceService<IConnectionStringResolver, MyDbPerTenantConnectionStringResolver>();
    	//...
    }
    		
    
    public class TestDbMigrator : AbpZeroDbMigrator<TestDbContext>
    {
    	public TestDbMigrator(IUnitOfWorkManager unitOfWorkManager,
    		IDbPerTenantConnectionStringResolver connectionStringResolver, IDbContextResolver dbContextResolver) : base(
    		unitOfWorkManager, connectionStringResolver, dbContextResolver)
    	{
    	}
    }
    
    
    
    _testDbMigrator.CreateOrMigrateForHost();
    
    
  • User Avatar
    0
    adamphones created

    Nope. Still the default connection string points to the default one...

    Both AbpZeroDbMigrator instance and TestAbpZeroDbMigrator instance contain the same default database connection string. I assume this shouldn't be the case.

    Configuration.ReplaceService<IConnectionStringResolver, MyDbPerTenantConnectionStringResolver>(); line doesn't seem to have any affect. I tried put the line in .EntityFrameworkCode module PreInitialize method and also tried it in Migrator module but still no luck.

    In .EntityFrameworkCore there is already Default module one as below

    Configuration.ReplaceService<IConnectionStringResolver, DefaultDbConnectionStringResolver>();

    here is well _connectionStringResolver always points to default database connection string.

    I started doubting that Migrator can be used to apply migration to multiple db context.. ?

  • User Avatar
    0
    maliming created
    Support Team

    hi

    Try to use the following code in the PreInitialize method of AbpZeroTemplateEntityFrameworkCoreModule

    IocManager.IocContainer.Register(
    	Component.For<IConnectionStringResolver, IDbPerTenantConnectionStringResolver>()
    		.ImplementedBy<MyDbPerTenantConnectionStringResolver>()
    		.Named(Guid.NewGuid().ToString())
    		.IsDefault()
    		.LifestyleTransient()
    );
    

  • User Avatar
    0
    adamphones created

    Finally worked! Even though the DefaultConnectionString still shows the default conecttionstring in the instance of _testMigration but the result is that the second database gets the migration with following registering.

    Thanks

    IocManager.IocContainer.Register( Component.For<IConnectionStringResolver, IDbPerTenantConnectionStringResolver>() .ImplementedBy<MyDbPerTenantConnectionStringResolver>() .Named(Guid.NewGuid().ToString()) .IsDefault() .LifestyleTransient()