多数据库适配机制
本文档引用的文件
/lmes-template/src/CMS.Plugin.MyPluginName.EntityFrameworkCore/CMSPluginEntityFrameworkCoreModule.cs/lmes-template/src/CMS.Plugin.MyPluginName.MySQL/CMSPluginMySQLModule.cs/lmes-template/src/CMS.Plugin.MyPluginName.PostgreSql/CMSPluginPostgreSqlModule.cs/lmes-template/src/CMS.Plugin.MyPluginName.SqlServer/CMSPluginSqlServerModule.cs/lmes-template/src/CMS.Plugin.MyPluginName.MySQL/CMSPluginDbContext.cs/lmes-template/src/CMS.Plugin.MyPluginName.Domain/CMSPluginDbProperties.cs/lmes-template/src/CMS.Plugin.MyPluginName.EntityFrameworkCore/CMSPluginEfCoreEntityExtensionMappings.cs/lmes-template/src/CMS.Plugin.MyPluginName.EntityFrameworkCore/Extensions/CMSPluginEfCoreExtensions.MyEntityName.cs/lmes-template/src/CMS.Plugin.MyPluginName.EntityFrameworkCore/appsettings.json
目录
引言
项目通过 ABP 模块和 Entity Framework Core 适配 MySQL、PostgreSQL、SQL Server。本文说明数据库模块的选择、加载与配置方式。
项目结构与模块化设计
项目采用分层模块化架构,将数据库适配逻辑分离到独立的模块中。每个数据库类型(MySQL、PostgreSQL、SQL Server)都有对应的独立项目,确保依赖隔离和可插拔性。
图示来源
/lmes-template/src/CMS.Plugin.MyPluginName.MySQL/CMSPluginMySQLModule.cs/lmes-template/src/CMS.Plugin.MyPluginName.PostgreSql/CMSPluginPostgreSqlModule.cs/lmes-template/src/CMS.Plugin.MyPluginName.SqlServer/CMSPluginSqlServerModule.cs
本节来源
/lmes-template/src/CMS.Plugin.MyPluginName.MySQL/CMSPluginMySQLModule.cs/lmes-template/src/CMS.Plugin.MyPluginName.PostgreSql/CMSPluginPostgreSqlModule.cs/lmes-template/src/CMS.Plugin.MyPluginName.SqlServer/CMSPluginSqlServerModule.cs
核心EF Core模块分析
CMSPluginEntityFrameworkCoreModule 是整个数据库访问层的基础模块,负责定义通用的EF Core配置和实体映射规则。
该模块通过继承 AbpModule 并依赖 CMSPluginDomainModule 和 AbpEntityFrameworkCoreModule,构建了持久化层的基础能力。其主要职责包括:
- 在
PreConfigureServices阶段调用CMSPluginEfCoreEntityExtensionMappings.Configure(),初始化实体扩展映射 - 提供统一的
DbContext配置入口点 - 定义抽象的数据访问契约(如
ICMSPluginDbContext)
图示来源
/lmes-template/src/CMS.Plugin.MyPluginName.EntityFrameworkCore/CMSPluginEntityFrameworkCoreModule.cs/lmes-template/src/CMS.Plugin.MyPluginName.EntityFrameworkCore/CMSPluginEfCoreEntityExtensionMappings.cs
本节来源
/lmes-template/src/CMS.Plugin.MyPluginName.EntityFrameworkCore/CMSPluginEntityFrameworkCoreModule.cs
数据库特定模块实现
针对每种数据库,项目提供了专门的适配模块:CMSPluginMySQLModule、CMSPluginPostgreSqlModule 和 CMSPluginSqlServerModule。这些模块均继承自 CMSPluginEntityFrameworkCoreModule,并在 ConfigureServices 方法中完成数据库提供程序的注册。
MySQL模块
options.UseMySQL(x => { ... });
通过 UseMySQL 方法指定MySQL数据库提供程序,并配置迁移历史表名称和模式。
PostgreSQL模块
options.UseNpgsql(x => { ... });
通过 UseNpgsql 方法指定PostgreSQL数据库提供程序,使用Npgsql驱动。
SQL Server模块
options.UseSqlServer(x => { ... });
通过 UseSqlServer 方法指定SQL Server数据库提供程序。
所有模块均在 OnModelCreating 中调用 builder.ConfigureMyEntityName() 来应用实体模型配置,并通过 CMSPluginDbProperties 统一管理数据库对象的命名约定(如表前缀、模式名等)。
图示来源
/lmes-template/src/CMS.Plugin.MyPluginName.MySQL/CMSPluginMySQLModule.cs/lmes-template/src/CMS.Plugin.MyPluginName.PostgreSql/CMSPluginPostgreSqlModule.cs/lmes-template/src/CMS.Plugin.MyPluginName.SqlServer/CMSPluginSqlServerModule.cs/lmes-template/src/CMS.Plugin.MyPluginName.MySQL/CMSPluginDbContext.cs
本节来源
/lmes-template/src/CMS.Plugin.MyPluginName.MySQL/CMSPluginMySQLModule.cs/lmes-template/src/CMS.Plugin.MyPluginName.PostgreSql/CMSPluginPostgreSqlModule.cs/lmes-template/src/CMS.Plugin.MyPluginName.SqlServer/CMSPluginSqlServerModule.cs
依赖注入与数据库提供程序替换机制
系统的数据库提供程序替换机制基于ABP框架的依赖注入容器和模块生命周期管理。
在 ConfigureServices 阶段,各数据库模块通过 Configure<AbpDbContextOptions> 覆盖默认的数据库提供程序配置。由于依赖注入容器的最后注册优先原则,最终生效的是最后加载的数据库模块配置。
关键实现点:
- 所有模块共享同一个
CMSPluginDbContext类型 - 通过
[ConnectionStringName]属性指定连接字符串名称,实现配置解耦 - 使用
AddAbpDbContext<T>注册上下文,由ABP框架管理生命周期 AbpDbContextOptions的UseXXX方法决定了实际使用的数据库提供程序
这种设计使得数据库提供程序的替换完全透明于上层业务代码。
本节来源
/lmes-template/src/CMS.Plugin.MyPluginName.MySQL/CMSPluginMySQLModule.cs/lmes-template/src/CMS.Plugin.MyPluginName.PostgreSql/CMSPluginPostgreSqlModule.cs/lmes-template/src/CMS.Plugin.MyPluginName.SqlServer/CMSPluginSqlServerModule.cs
运行时动态加载模块原理
系统通过ABP模块系统的依赖关系和启动顺序控制,实现运行时动态加载目标数据库模块。
实现原理如下:
- 主模块
CMSPluginModule依赖CMSPluginEntityFrameworkCoreModule - 各数据库模块均依赖
CMSPluginEntityFrameworkCoreModule - 在应用程序启动时,根据实际引用的数据库模块(仅引用一个),加载对应的
CMSPluginXXXModule - 该模块在
ConfigureServices中注册特定的数据库提供程序 - 依赖注入容器最终使用最后注册的配置
此机制允许通过简单的项目引用切换来改变数据库后端,无需修改任何代码。
图示来源
/lmes-template/src/CMS.Plugin.MyPluginName/CMSPluginModule.cs/lmes-template/src/CMS.Plugin.MyPluginName.EntityFrameworkCore/CMSPluginEntityFrameworkCoreModule.cs/lmes-template/src/CMS.Plugin.MyPluginName.MySQL/CMSPluginMySQLModule.cs
本节来源
/lmes-template/src/CMS.Plugin.MyPluginName/CMSPluginModule.cs
配置示例与切换步骤
配置示例
appsettings.json 中的连接字符串配置:
{
"ConnectionStrings": {
"Default": "Server=127.0.0.1;Database=CMS.Plugin.MyPluginName;User ID=root;Password=123456"
}
}
切换步骤
- 在主项目中移除当前数据库模块的引用
- 添加目标数据库模块的引用(如从MySQL切换到SQL Server)
- 确保
appsettings.json中的连接字符串符合目标数据库格式 - 重新生成并部署应用
例如,切换到SQL Server时,连接字符串应改为:
"Default": "Server=localhost;Database=CMSPlugin;User Id=sa;Password=your_password;"
本节来源
/lmes-template/src/CMS.Plugin.MyPluginName.EntityFrameworkCore/appsettings.json
迁移脚本与数据类型映射兼容性注意事项
迁移脚本注意事项
- 各数据库模块包含独立的
UpdateMigrations.bat和UpdateDB.bat脚本 - 迁移历史表通过
MigrationsHistoryTable()方法统一命名,避免冲突 - 实体配置中使用
CMSPluginDbProperties.DbTablePrefix确保表名一致性
数据类型映射兼容性
- 字符串长度映射:MySQL使用
VARCHAR,PostgreSQL使用character varying,SQL Server使用NVARCHAR - 文本字段:长文本建议使用
TEXT(MySQL)、TEXT(PostgreSQL)、NVARCHAR(MAX)(SQL Server) - 布尔类型:MySQL使用
TINYINT(1),PostgreSQL使用BOOLEAN,SQL Server使用BIT - 时间类型:统一使用
datetime2(SQL Server)、TIMESTAMP(MySQL)、TIMESTAMP(PostgreSQL)以保证精度
建议在实体配置中避免使用数据库特有类型,优先使用EF Core的标准类型映射。
本节来源
/lmes-template/src/CMS.Plugin.MyPluginName.EntityFrameworkCore/Extensions/CMSPluginEfCoreExtensions.MyEntityName.cs/lmes-template/src/CMS.Plugin.MyPluginName.Domain/CMSPluginDbProperties.cs
总结
MySQL、PostgreSQL 和 SQL Server 通过独立模块适配,主要配置如下:
- 以
CMSPluginEntityFrameworkCoreModule为基础,提供统一的数据访问抽象 - 各数据库模块通过覆盖
AbpDbContextOptions实现提供程序替换 - 依赖注入容器和模块生命周期管理确保运行时正确配置
- 统一的命名约定和实体配置保证跨数据库兼容性
其他数据库可参照这三种适配模块的结构进行扩展。