3

The specified transaction is not associated with the current connection. Only transactions associated with the current connection may be used.

How do I use multiple DbContext in one transaction?

Update 1

If I use ExistingConnection, then all the DbContext will use the same connection string.

Did I add multiple DbContext in the wrong way?

In EntityFrameworkModule:

public override void PreInitialize()
{
    var configuration = AppConfigurations.Get(WebContentDirectoryFinder.CalculateContentRootFolder());

    Configuration.Modules.AbpEfCore().AddDbContext<BPDbContext>(options =>
    {
        if (options.ExistingConnection != null)
        {
            options.DbContextOptions.UseSqlServer(options.ExistingConnection);
        }
        else
        {
            options.DbContextOptions.UseSqlServer(configuration.GetConnectionString(ABPCoreConsts.BPConnectionStringName));
        }

        //options.DbContextOptions.UseSqlServer(
        //    configuration.GetConnectionString(ABPCoreConsts.BPConnectionStringName));
    });

    Configuration.Modules.AbpEfCore().AddDbContext<EPlusDBConext>(options =>
    {
        if (options.ExistingConnection != null)
        {
            options.DbContextOptions.UseSqlServer(options.ExistingConnection);
        }
        else
        {
            options.DbContextOptions.UseSqlServer(configuration.GetConnectionString(ABPCoreConsts.EECPlusConnectionStringName));
        }

        //options.DbContextOptions.UseSqlServer(
        //    configuration.GetConnectionString(ABPCoreConsts.EECPlusConnectionStringName));
    });

    Configuration.Modules.AbpEfCore().AddDbContext<ProjectManageDbContext>(options =>
    {
        if (options.ExistingConnection != null)
        {
            options.DbContextOptions.UseSqlServer(options.ExistingConnection);
        }
        else
        {
            options.DbContextOptions.UseSqlServer(configuration.GetConnectionString(ABPCoreConsts.PMConnectionStringName));
        }

        //options.DbContextOptions.UseSqlServer(
        //    configuration.GetConnectionString(ABPCoreConsts.PMConnectionStringName));
    });

    RegisterGenericRepositories();
}

Update 2

I got it to work by implementing IConnectionStringResolver for custom connections:

public class MyDBConnectionStringResolver : DefaultConnectionStringResolver
{
    public override string GetNameOrConnectionString(ConnectionStringResolveArgs args)
    {
        var configuration = AppConfigurations.Get(WebContentDirectoryFinder.CalculateContentRootFolder());

        switch (args["DbContextType"].ToString())
        {
            case "ABPCore.EPlusDBConext":
                return configuration.GetConnectionString(ABPCoreConsts.EECPlusConnectionStringName);
            case "ABPCore.BPDbContext":
                return configuration.GetConnectionString(ABPCoreConsts.BPConnectionStringName);
            case "ABPCore.ProjectManageDbContext":
                return configuration.GetConnectionString(ABPCoreConsts.PMConnectionStringName);
        }

        return string.Empty;
    }
}

Don't forget to replace service in EntityFrameworkModule's PreInitialize method:

Configuration.ReplaceService<IConnectionStringResolver, MyDbConnectionStringResolver>(DependencyLifeStyle.Transient);
aaron
  • 39,695
  • 6
  • 46
  • 102
Bivozeou
  • 33
  • 1
  • 6

1 Answers1

4

Add this in *DbContextConfigurer.cs:

public static void Configure(DbContextOptionsBuilder<*DbContext> builder, DbConnection connection)
{
    builder.UseSqlServer(connection);
}

Change this in *EntityFrameworkModule.cs:

public override void PreInitialize()
{
    if (!SkipDbContextRegistration)
    {
        Configuration.Modules.AbpEfCore().AddDbContext<*DbContext>(options =>
        {
            if (options.ExistingConnection != null)
            {
                options.DbContextOptions.UseSqlServer(options.ExistingConnection);
            }
            else
            {
                options.DbContextOptions.UseSqlServer(options.ConnectionString);
            }
        });
    }
}

Reference: https://github.com/aspnetboilerplate/module-zero-core-template/commit/da522e76ca2ecefdb7670f009f78575c5b97b4a0


Important

If each DbContext has its own connection string, you need to implement IConnectionStringResolver as explained here and replace the service:

Configuration.ReplaceService<IConnectionStringResolver, MyConnectionStringResolver>(DependencyLifeStyle.Transient);
aaron
  • 39,695
  • 6
  • 46
  • 102
  • if i usd existing connection ,the multiple dbcontext will use one connectionstring , it will throw SqlException: Invalid object name 'tablexxx', is that i'm add multiple dbcontext in wrong way? i add dbcontext at EntityFrameworkModule, PreInitialize – Bivozeou Oct 12 '17 at 01:31
  • i'm sure when i debug ,existing connection is same, my code in https://github.com/BivoZeou/ABPCore here you can see – Bivozeou Oct 12 '17 at 02:34
  • Can you implement and replace `IConnectionStringResolver` as explained [here](https://github.com/aspnetboilerplate/aspnetboilerplate/pull/1834#issuecomment-326041970)? You have the same issue as [this](https://github.com/aspnetboilerplate/aspnetboilerplate/issues/2325). – aaron Oct 12 '17 at 03:04
  • i'm impl IConnectionStringResolver ,it's work!, thanks a lot ! – Bivozeou Oct 12 '17 at 06:58
  • You're welcome! I'll update my answer with that so others can benefit :) – aaron Oct 12 '17 at 06:59