IDomainService 中的 ABP EF Core 多个 DbContext 访问抛出事务错误

ABP EF Core multiple DbContext access in IDomainService throws transaction error

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

如何在一个事务中使用多个 DbContext?

更新 1

如果我使用 ExistingConnection, 那么所有的 DbContext 将使用相同的连接字符串。

我是否以错误的方式添加了多个 DbContext?

在 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();
}

更新 2

我通过为自定义连接实施 IConnectionStringResolver 使其工作:

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;
    }
}

不要忘记替换 EntityFrameworkModule 的 PreInitialize 方法中的服务:

Configuration.ReplaceService<IConnectionStringResolver, MyDbConnectionStringResolver>(DependencyLifeStyle.Transient);

*DbContextConfigurer.cs中添加:

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

*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);
            }
        });
    }
}

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


重要

如果每个 DbContext 都有自己的连接字符串,您需要按照 here 的说明实施 IConnectionStringResolver 并替换服务:

Configuration.ReplaceService<IConnectionStringResolver, MyConnectionStringResolver>(DependencyLifeStyle.Transient);