ABP netcore多数据库连接,动态链接字符串
ABP框架相信大家都有些了解,今天我们来尝试用ABP框架来实现多数据库访问,第二数据库使用动态链接字符串。
前段时间想做一个用ABP框架作为多租户管理基础框架,保存企业用户的一些基本信息,如企业资料,主要负责人资料。后期会加上租户的租期及费用问题。然后重点是每个企业都现有进销存业务数据库,想把之前客户本地部署的进销存软件上云,然后扩展互联网服务。当然我们不用ABP框架也可以实现,但是手上已有ABP框架开发的在线商城和移动端接口服务,所以想集成进来做个大统一。
问题是怎么在ABP现有的数据库框架上把我们每个租户现有的业务数据整合进来。
首先各个企业现有数据库结构基本一致,因为是同一套进销存cs软件,数据库sql2000-sql2014都有,部署的位置有些已上云,有些还在本地数据库里部署。
既然结构一样,我们就同一套代码使用不同的数据库连接字符串即可。
首先用EFCORE生成进销存数据库模型,得到DbSecondContext上下文
然后根据官方多数据库访问文档https://github.com/aspnetboilerplate/aspnetboilerplate-samples/tree/master/MultipleDbContextEfCoreDemo,给了很重要的提示,但是没有说明如何动态改变连接字符串。
两个数据库上下文可以根据官方文档构建。
实现动态改变连接字符串
public class MyConnectionStringResolver:DefaultConnectionStringResolver
{
private readonly IConfigurationRoot _appConfiguration;
public Abp.Runtime.Session.IAbpSession AbpSession { get; set; }
private readonly ICurrentUnitOfWorkProvider _currentUnitOfWorkProvider;
private readonly MultiTenancy.TenantManager _tenantManager;
public MyConnectionStringResolver(IAbpStartupConfiguration configuration,
IHostingEnvironment hostingEnvironment,
ICurrentUnitOfWorkProvider currentUnitOfWorkProvider,
MultiTenancy.TenantManager tenantManager
)
: base(configuration)
{
_appConfiguration =
AppConfigurations.Get(hostingEnvironment.ContentRootPath, hostingEnvironment.EnvironmentName);
_currentUnitOfWorkProvider = currentUnitOfWorkProvider;
AbpSession = Abp.Runtime.Session.NullAbpSession.Instance;
_tenantManager = tenantManager;
}
public override string GetNameOrConnectionString(ConnectionStringResolveArgs args)
{
if (args["DbContextConcreteType"] as Type == typeof(DbSecondServer.DbSecondEntityFrameworkCore.Models.DbSecondContext))
{
var tenant = _tenantManager.GetById(GetCurrentTenantId().GetValueOrDefault());
var str= "Server=" + tenant.DatabaseServer + "; Database=" + tenant.DatabaseName + "; Uid=" + tenant.DatabaseUid + ";Password=" + tenant.DatabasePassword + ";"; //租户类里加了链接字符串的4参数
return str;
}
return base.GetNameOrConnectionString(args);
}
protected virtual int? GetCurrentTenantId()
{
return _currentUnitOfWorkProvider.Current != null
? _currentUnitOfWorkProvider.Current.GetTenantId()
: AbpSession.TenantId;
}
}
注意事项:因为涉及到sql2000和sql2005在使用ABP分页时会有问题,所以在DbSecondContextOptionsConfigurer中:
public class DbSecondOptionsConfigurer
{
public static void Configure(DbContextOptionsBuilder<DbSecondContext> builder, string connectionString)
{
builder.UseSqlServer(connectionString, b => b.UseRowNumberForPaging());//后面半句解决sql2005、sql2008:不支持在 FETCH 语句中选项 NEXT 的用法无效
}
public static void Configure(DbContextOptionsBuilder<DbSecondContext> builder, DbConnection connection)
{
builder.UseSqlServer(connection, b => b.UseRowNumberForPaging());//后面半句解决sql2005、sql2008:不支持在 FETCH 语句中选项 NEXT 的用法无效
}
}`
花了好几天研究。第一次写不足之处见谅。