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);
}
});
}
}
重要
如果每个 DbContext
都有自己的连接字符串,您需要按照 here 的说明实施 IConnectionStringResolver
并替换服务:
Configuration.ReplaceService<IConnectionStringResolver, MyConnectionStringResolver>(DependencyLifeStyle.Transient);
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);
}
});
}
}
重要
如果每个 DbContext
都有自己的连接字符串,您需要按照 here 的说明实施 IConnectionStringResolver
并替换服务:
Configuration.ReplaceService<IConnectionStringResolver, MyConnectionStringResolver>(DependencyLifeStyle.Transient);