Skip to content

9.19 多种数据库操作

📝 模块更新日志 问题修复*

+ 修复 最新版的 `EFCore 9.0.0-preview.5` 不支持 `SQL Server 2008/2005/2000` 数据库 4\.9\.4\.2 ⏱️2024\.06\.21 [6fef13e](https://gitee.com/dotnetchina/Furion/commit/6fef13e0f825d1eb1f5ff414f8dcd3a0de77be2e)

连接字符串配置注意事项如果连接字符串是配置在自定义的 .json 文件中,那么必须在 Visual Studio 中配置 .json 右键属性,设置 复制 输出目录为 如果较新则复制,生成操作为 内容

否则就会提示找不到配置或连接字符串的错误。

9.19.1 Furion 支持数据库提供器

SqlServer Sqlite Cosmos InMemoryDatabase MySql PostgreSQL Oracle Firebird Dm

9.19.1.1 数据库提供器对应包

  • SqlServerMicrosoft.EntityFrameworkCore.SqlServer (支持 SqlServer 2005 +)
  • SqliteMicrosoft.EntityFrameworkCore.Sqlite
  • CosmosMicrosoft.EntityFrameworkCore.Cosmos
  • InMemoryDatabaseMicrosoft.EntityFrameworkCore.InMemory
  • MySql
    • Pomelo.EntityFrameworkCore.MySql:(支持 MySql 5.x +)
    • MySql.EntityFrameworkCore:支持 (MySql 8.x +)
  • PostgreSQLNpgsql.EntityFrameworkCore.PostgreSQL
  • OracleOracle.EntityFrameworkCore (支持 Oracle 10 +)
  • FirebirdFirebirdSql.EntityFrameworkCore.Firebird
  • DmMicrosoft.EntityFrameworkCore.Dm

小知识这些数据库包应该安装在 Furion.EntityFramework.Core 层。特殊情况需安装在 Furion.Core 层中,如 Mysql HasCharset() 配置。

9.19.2 多数据库服务注册

// 注册 SqlServer  
options.AddDbPool<FurionDbContext>(DbProvider.SqlServer);  
options.AddDbPool<FurionDbContext>($"{DbProvider.SqlServer}@2005"); // 支持 2005 数据库  
options.AddDbPool<FurionDbContext>($"{DbProvider.SqlServer}@2008"); // 支持 2008 数据库  

// 注册 Sqlite  
options.AddDbPool<FurionDbContext>(DbProvider.Sqlite);  

// 注册 Cosmos  
options.AddDbPool<FurionDbContext>(DbProvider.Cosmos);  

// 注册 InMemoryDatabase  
options.AddDbPool<FurionDbContext>(DbProvider.InMemoryDatabase);  

// 注册 MySql  
options.AddDbPool<FurionDbContext>(DbProvider.MySql);  
options.AddDbPool<FurionDbContext>($"{DbProvider.MySql}@8.0.22");  // 可以指定版本号  
options.AddDbPool<FurionDbContext>(DbProvider.MySqlOfficial);   // 使用 MySql 官方包(MySql.EntityFrameworkCore)  

// 注册 PostgreSQL  
options.AddDbPool<FurionDbContext>(DbProvider.Npgsql);  

// 注册 Oracle  
options.AddDbPool<FurionDbContext>(DbProvider.Oracle);  
options.AddDbPool<FurionDbContext>($"{DbProvider.Oracle}@11");  // 支持 Oracle 11 版本  

// 注册 Firebird  
options.AddDbPool<FurionDbContext>(DbProvider.Firebird);  

// 注册 Dm  
options.AddDbPool<FurionDbContext>(DbProvider.Dm);  

新版 SqlServer/MySQL/Oracle 注意SqlServer 兼容 2005-2008 写法:

services.AddDatabaseAccessor(options =>  
{  
    options.AddDbPool<FurionDbContext>($"{DbProvider.SqlServer}@2005"); // 支持 2005 数据库  
    options.AddDbPool<FurionDbContext>($"{DbProvider.SqlServer}@2008"); // 支持 2008 数据库  
});  

MySQL 兼容旧版本(带版本号)写法:

services.AddDatabaseAccessor(options =>  
{  
    options.AddDbPool<FurionDbContext>($"{DbProvider.MySql}@8.0.22");  
});  

如果使用了 MySql.EntityFrameworkCore 包,则需改为以下注册:

services.AddDatabaseAccessor(options =>  
{  
    options.AddDbPool<FurionDbContext>(DbProvider.MySqlOfficial);  
});  

Oracle 兼容 11 版本

services.AddDatabaseAccessor(options =>  
{  
    // 正常这样配置即可  
    options.AddDbPool<FurionDbContext>($"{DbProvider.Oracle}@11");  

    // 如果依然出现 ORA-00933: SQL 错误,可以尝试以下配置:  
    options.AddDbPool<FurionDbContext>($"{DbProvider.Oracle}@11", optionBuilder: (ses, opt) =>  
    {  
        opt.UseOracle(b => b.UseOracleSQLCompatibility("11"));  
    });  
});  

9.19.3 各类数据库连接字符串配置示例

  • SqliteData Source=./Furion.db
  • MySqlData Source=localhost;Database=Furion;User ID=root;Password=000000;pooling=true;port=3306;sslmode=none;CharSet=utf8;
  • SqlServerServer=localhost;Database=Furion;User=sa;Password=000000;MultipleActiveResultSets=True;Encrypt=True;TrustServerCertificate=True;
  • OracleUser Id=orcl;Password=orcl;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=orcl)))
  • PostgreSQLPORT=5432;DATABASE=postgres;HOST=127.0.0.1;PASSWORD=postgres;USER ID=postgres;

9.19.4 多数据库使用方式

Furion 通过独创的 数据库上下文定位器 实现多数据库灵活操作切换。只需要为每一种数据库绑定唯一的数据库上下文定位器即可。

以下是 Furion 支持多数据库操作的实例:

9.19.4.1 实体仓储方式

// 切换到 MSSQL 操作 Person表  
var mssqlRepository = personRepository.Change<Person, MsSqlDbContextLocator>();  

// 切换到 MySql 操作 Person表  
var mysqlRepository = personRepository.Change<Person, MySqlDbContextLocator>();  

// 切换到 Sqlite 操作 Person表  
var sqliteRepository = personRepository.Change<Person, SqliteDbContextLocator>();  


9.19.4.2 非泛型仓储方式

// 切换到 MSSQL 操作 Person表  
var mssqlRepository = repository.Change<Person, MsSqlDbContextLocator>();  

// 切换到 MySql 操作 Person表  
var mysqlRepository = repository.Change<Person, MySqlDbContextLocator>();  

// 切换到 Sqlite 操作 Person表  
var sqliteRepository = repository.Change<Person, SqliteDbContextLocator>();  

9.19.4.3 Sql 仓储方式

// 切换到 MSSQL 操作 Person表  
var mssqlRepository = sqlRepository.Change<MsSqlDbContextLocator>();  

// 切换到 MySql 操作 Person表  
var mysqlRepository = sqlRepository.Change<MySqlDbContextLocator>();  

// 切换到 Sqlite 操作 Person表  
var sqliteRepository = sqlRepository.Change<SqliteDbContextLocator>();  

9.19.4.4 实体定义方式


// 支持一个数据库  
public class Person: IEntity<MySqlDbContextLocator>  
{  
    // ....  
}  

// 支持多个数据库  
public class Person: IEntity<MySqlDbContextLocator, SqliteDbContextLocator>  
{  
    // ....  
}  

小知识所有的 实体依赖接口或抽象类 都支持泛型方式 指定 数据库上下文定位器,最多支持 8 个。

9.19.4.5 Linq 函数方式

public static class QueryFunctions  
{  
    [QueryableFunction("FN_GetId", "dbo", typeof(MySqlDbContextLocator), typeof(SqliteDbContextLocator))]  
    public static int GetId(int id) => throw new NotSupportedException();  
}  

9.19.5 SqlServer 低版本支持动态配置

正常情况下,只需要在注册的时候指定 @2008 数据库即可,有些时候我们可能需要在 DbContextOnConfigure 中配置,这个时候就需要添加以下代码:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)  
{  
    optionsBuilder.UseSqlServer(DbProvider.GetConnectionString<TDbContext>())  
                  .ReplaceService<IQueryTranslationPostprocessorFactory, SqlServer2008QueryTranslationPostprocessorFactory>();  
    base.OnConfiguring(optionsBuilder);  
}  

小知识DbProvider.GetConnectionString<TDbContext>() 是获取对应上下文配置的数据库链接字符串。

9.19.6 MySql 时区问题/少 8 小时问题

可查阅相关 Issuehttps://gitee.com/dotnetchina/Furion/issues/I3RSCO

9.19.7 snake_case 风格表名和字段

默认情况下 EFCore 将使用和模型定义一致的方式定义表和字段,但可以通过 https://github.com/efcore/EFCore.NamingConventions 拓展插件改变此行为,如下图所示:

 builder.UseNpgsql()  
        .UseLowerCaseNamingConvention();  

其他资料:https://www.npgsql.org/efcore/modeling/table-column-naming.html

9.19.8 反馈与建议

与我们交流给 Furion 提 Issue