YiShaAdmin多数据库支持:MySQL与SQL Server的适配方案

YiShaAdmin多数据库支持:MySQL与SQL Server的适配方案

【免费下载链接】YiShaAdmin 基于 .NET Core MVC 的权限管理系统,代码易读易懂、界面简洁美观 【免费下载链接】YiShaAdmin 项目地址: https://gitcode.com/GitHub_Trending/yi/YiShaAdmin

你是否在开发企业级应用时,面临过需要同时支持多种数据库的困扰?比如公司内部系统长期使用SQL Server,而新项目又要求使用MySQL。YiShaAdmin作为一款基于.NET Core MVC的权限管理系统,通过精心设计的数据库适配层,完美解决了这一痛点。本文将详细介绍YiShaAdmin如何实现MySQL与SQL Server的无缝切换,读完你将掌握多数据库支持的核心设计思想和实操方法。

一、多数据库支持的核心架构

YiShaAdmin采用接口抽象与具体实现分离的设计模式,通过定义统一的数据访问接口,为不同数据库提供专属实现。这种设计不仅保证了代码的可扩展性,还使得业务逻辑层无需关心底层数据库类型。

1.1 IDatabase接口定义

IDatabase接口定义了所有数据库操作的标准方法,包括CRUD(创建、读取、更新、删除)操作、事务管理、SQL执行等。业务逻辑层通过依赖注入该接口,实现对不同数据库的透明访问。

核心接口定义如下(完整代码见YiSha.Data/YiSha.Data/IDatabase.cs):

public interface IDatabase
{
    // 事务管理
    Task<IDatabase> BeginTrans();
    Task<int> CommitTrans();
    Task RollbackTrans();
    
    // CRUD操作
    Task<int> Insert<T>(T entity) where T : class;
    Task<int> Update<T>(T entity) where T : class;
    Task<int> Delete<T>(Expression<Func<T, bool>> condition) where T : class, new();
    Task<T> FindEntity<T>(Expression<Func<T, bool>> condition) where T : class, new();
    Task<IEnumerable<T>> FindList<T>(Expression<Func<T, bool>> condition) where T : class, new();
    
    // SQL执行
    Task<int> ExecuteBySql(string strSql, params DbParameter[] dbParameter);
    Task<DataTable> FindTable(string strSql, DbParameter[] dbParameter);
}

1.2 数据库适配架构图

YiShaAdmin的数据库适配层主要由以下几个部分组成:

mermaid

从架构图可以看出,业务逻辑层(F)仅依赖IDatabase接口(A),具体使用MySQL还是SQL Server,由配置文件(G)中的数据库类型设置决定。这种设计使得切换数据库时,无需修改业务代码,只需更改配置即可。

二、MySQL与SQL Server的实现差异

虽然IDatabase接口定义了统一的方法,但MySQL和SQL Server在SQL语法、分页查询、事务处理等方面存在差异。YiShaAdmin通过为每种数据库提供专属实现类,处理这些差异。

2.1 MySQL实现:MySqlDatabase

MySqlDatabase类实现了IDatabase接口,针对MySQL的特性进行了优化。例如,MySQL使用LIMIT子句进行分页,MySqlDatabase在实现分页查询时,会自动生成包含LIMIT的SQL语句。

核心实现代码片段(完整代码见YiSha.Data/YiSha.Data.EF/Database/MySqlDatabase.cs):

public async Task<(int total, DataTable)> FindTable(string strSql, DbParameter[] dbParameter, string sort, bool isAsc, int pageSize, int pageIndex)
{
    using (var dbConnection = dbContext.Database.GetDbConnection())
    {
        DbHelper dbHelper = new DbHelper(dbContext, dbConnection);
        StringBuilder sb = new StringBuilder();
        // 生成MySQL分页SQL
        sb.Append(DatabasePageExtension.MySqlPageSql(strSql, dbParameter, sort, isAsc, pageSize, pageIndex));
        object tempTotal = await dbHelper.ExecuteScalarAsync(CommandType.Text, "SELECT COUNT(1) FROM (" + strSql + ") T", dbParameter);
        int total = tempTotal.ParseToInt();
        if (total > 0)
        {
            var reader = await dbHelper.ExecuteReadeAsync(CommandType.Text, sb.ToString(), dbParameter);
            DataTable resultTable = DatabasesExtension.IDataReaderToDataTable(reader);
            return (total, resultTable);
        }
        else
        {
            return (total, new DataTable());
        }
    }
}

2.2 SQL Server实现:SqlServerDatabase

与MySqlDatabase类似,SqlServerDatabase类针对SQL Server的特性进行了适配。例如,SQL Server使用TOP关键字和ROW_NUMBER()函数进行分页,SqlServerDatabase会生成相应的分页SQL。

核心实现代码片段(完整代码见YiSha.Data/YiSha.Data.EF/Database/SqlServerDatabase.cs):

public async Task<(int total, DataTable)> FindTable(string strSql, DbParameter[] dbParameter, string sort, bool isAsc, int pageSize, int pageIndex)
{
    using (var dbConnection = dbContext.Database.GetDbConnection())
    {
        DbHelper dbHelper = new DbHelper(dbContext, dbConnection);
        StringBuilder sb = new StringBuilder();
        // 生成SQL Server分页SQL
        sb.Append(DatabasePageExtension.SqlServerPageSql(strSql, dbParameter, sort, isAsc, pageSize, pageIndex));
        object tempTotal = await dbHelper.ExecuteScalarAsync(CommandType.Text, "SELECT COUNT(1) FROM (" + strSql + ") T", dbParameter);
        int total = tempTotal.ParseToInt();
        if (total > 0)
        {
            var reader = await dbHelper.ExecuteReadeAsync(CommandType.Text, sb.ToString(), dbParameter);
            DataTable resultTable = DatabasesExtension.IDataReaderToDataTable(reader);
            return (total, resultTable);
        }
        else
        {
            return (total, new DataTable());
        }
    }
}

2.3 关键差异对比

功能MySQL实现SQL Server实现
分页查询使用LIMIT offset, rowcount使用ROW_NUMBER() OVER (ORDER BY ...)
自增主键通常使用AUTO_INCREMENT通常使用IDENTITY(1,1)
字符串连接使用CONCAT()函数使用+运算符或CONCAT()函数
日期函数DATE_FORMAT()CONVERT()FORMAT()

YiShaAdmin在实现层面对这些差异进行了封装,确保业务逻辑层调用统一接口时,能得到正确的结果,无需关心底层数据库的具体实现。

三、数据库脚本与初始化

为了支持多数据库,YiShaAdmin提供了针对MySQL和SQL Server的初始化脚本,包括数据库结构创建和初始数据插入。

3.1 数据库脚本文件

项目中提供的数据库脚本文件位于Document/DatabaseScript/目录下,主要包括:

  • mysql.sql: MySQL数据库结构创建脚本
  • mysql_data.sql: MySQL初始数据插入脚本
  • sqlserver.sql: SQL Server数据库结构创建脚本
  • sqlserver_data.sql: SQL Server初始数据插入脚本

这些脚本文件确保了在不同数据库环境下,都能快速搭建起一致的数据库结构和初始数据。

3.2 数据库表结构设计

YiShaAdmin的数据库表结构设计充分考虑了兼容性,尽量使用标准SQL类型。例如,字符串类型统一使用VARCHAR,避免使用数据库特有类型(如MySQL的TEXT或SQL Server的NVARCHAR(MAX))。

以用户表(sys_user)为例,其在MySQL和SQL Server中的定义分别如下:

MySQL (mysql.sql):

CREATE TABLE `sys_user` (
  `Id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `UserName` varchar(50) NOT NULL COMMENT '用户名',
  `Password` varchar(100) NOT NULL COMMENT '密码',
  `RealName` varchar(50) DEFAULT NULL COMMENT '真实姓名',
  `Gender` tinyint(4) DEFAULT NULL COMMENT '性别(0-未知,1-男,2-女)',
  `Phone` varchar(20) DEFAULT NULL COMMENT '手机号',
  `Email` varchar(100) DEFAULT NULL COMMENT '邮箱',
  `CreateTime` datetime NOT NULL COMMENT '创建时间',
  `UpdateTime` datetime DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

SQL Server (sqlserver.sql):

CREATE TABLE [dbo].sys_user NOT NULL,
  [UserName] varchar NOT NULL,
  [Password] varchar NOT NULL,
  [RealName] varchar NULL,
  [Gender] [tinyint] NULL,
  [Phone] varchar NULL,
  [Email] varchar NULL,
  [CreateTime] [datetime] NOT NULL,
  [UpdateTime] [datetime] NULL,
  CONSTRAINT [PK_sys_user] PRIMARY KEY CLUSTERED ([Id] ASC)
) ON [PRIMARY];
GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'主键' , @level0type=N'SCHEMA',@level0name=N'dbo',@level1type=N'TABLE',@level1name=N'sys_user',@level2type=N'COLUMN',@level2name=N'Id'
GO

可以看出,除了自增主键的定义方式不同(MySQL使用AUTO_INCREMENT,SQL Server使用IDENTITY(1,1)),表结构基本一致,这为多数据库支持奠定了基础。

四、配置与切换

YiShaAdmin通过配置文件实现数据库类型的切换,无需修改代码。下面介绍如何在项目中配置和切换数据库。

4.1 配置文件设置

appsettings.json中,通过DatabaseTypeConnectionString配置数据库类型和连接字符串:

{
  "ConnectionStrings": {
    "MySql": "server=localhost;database=yishaadmin;uid=root;pwd=123456;port=3306;charset=utf8mb4;",
    "SqlServer": "Server=localhost;Database=yishaadmin;User Id=sa;Password=123456;TrustServerCertificate=True;"
  },
  "DatabaseType": "MySql" // 可选值: MySql, SqlServer
}

4.2 依赖注入配置

Startup.cs中,根据配置文件的DatabaseType,注入相应的数据库实现:

public void ConfigureServices(IServiceCollection services)
{
    // 读取数据库配置
    var databaseType = Configuration["DatabaseType"];
    var connectionString = Configuration.GetConnectionString(databaseType);
    
    // 根据数据库类型注入相应的IDatabase实现
    if (databaseType == "MySql")
    {
        services.AddScoped<IDatabase>(provider => new MySqlDatabase(connectionString));
    }
    else if (databaseType == "SqlServer")
    {
        services.AddScoped<IDatabase>(provider => new SqlServerDatabase(connectionString));
    }
    
    // 其他服务配置...
}

通过这种方式,业务逻辑层在需要使用数据库操作时,只需通过构造函数注入IDatabase接口即可,无需关心具体实现:

public class UserService
{
    private readonly IDatabase _database;
    
    // 构造函数注入IDatabase
    public UserService(IDatabase database)
    {
        _database = database;
    }
    
    // 使用IDatabase进行数据库操作
    public async Task<UserEntity> GetUserById(long id)
    {
        return await _database.FindEntity<UserEntity>(id);
    }
}

4.3 运行时切换

如果需要在运行时动态切换数据库,YiShaAdmin还支持通过代码修改配置并重新初始化数据库连接。不过,在大多数场景下,建议在应用启动时确定数据库类型。

五、实际应用场景与最佳实践

5.1 应用场景

YiShaAdmin的多数据库支持适用于以下场景:

  1. 企业内部系统整合:同一套系统需要部署在使用不同数据库的部门。
  2. 产品化软件:作为通用权限管理系统,需要适应客户现有的数据库环境。
  3. 开发与生产环境分离:开发环境使用MySQL(轻量、免费),生产环境使用SQL Server(企业级特性)。

5.2 最佳实践

  1. 使用参数化查询:避免直接拼接SQL字符串,防止SQL注入,同时提高查询性能。
  2. 避免使用数据库特有函数:业务逻辑中尽量使用标准SQL函数,如必须使用特有函数,通过数据库适配层封装。
  3. 测试覆盖:确保所有功能在两种数据库环境下都经过充分测试。
  4. 监控与日志:记录数据库操作日志,便于排查跨数据库兼容性问题。

5.3 项目截图展示

YiShaAdmin的管理界面简洁美观,以下是系统运行在MySQL环境下的截图:

YiShaAdmin登录界面

YiShaAdmin用户管理界面

这些界面在SQL Server环境下完全一致,体现了多数据库支持的透明性。

六、总结与展望

YiShaAdmin通过接口抽象、具体实现分离的设计模式,结合针对性的数据库适配代码,实现了对MySQL和SQL Server的完美支持。这种设计不仅保证了代码的可扩展性,还使得业务逻辑层与底层数据库解耦,大大降低了维护成本。

未来,YiShaAdmin计划进一步扩展数据库支持范围,包括PostgreSQL、Oracle等主流数据库。同时,将引入数据库连接池管理、读写分离等高级特性,提升系统在高并发场景下的性能。

如果你正在寻找一款支持多数据库的权限管理系统,或者想学习多数据库适配的设计思想,YiShaAdmin无疑是一个优秀的选择。项目代码易读易懂,文档齐全,欢迎通过以下方式获取和参与项目:

希望本文对你理解多数据库支持有所帮助,欢迎在项目中实践并提出宝贵意见!

点赞+收藏+关注,获取更多YiShaAdmin使用技巧和最佳实践!下期预告:《YiShaAdmin权限管理深度解析》。

【免费下载链接】YiShaAdmin 基于 .NET Core MVC 的权限管理系统,代码易读易懂、界面简洁美观 【免费下载链接】YiShaAdmin 项目地址: https://gitcode.com/GitHub_Trending/yi/YiShaAdmin

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值