在C#企业级开发中,多数据库切换是常见需求,比如业务数据存MySQL、日志数据存SQL Server,或者需要同时对接不同厂商的数据库实例。Entity Framework作为常用的ORM框架,支持通过配置实现多数据源的灵活切换,无需修改大量业务代码。

核心实现思路
多数据库切换的核心是为不同的数据库配置独立的DbContext实例,每个DbContext对应不同的数据库连接字符串和数据库驱动,再通过依赖注入管理这些DbContext的生命周期,业务层根据需求获取对应的上下文实例即可。
环境准备
首先需要安装对应的EF数据库驱动包,以MySQL和SQL Server为例,需要安装以下NuGet包:
- Microsoft.EntityFrameworkCore.SqlServer
- Microsoft.EntityFrameworkCore.MySql(推荐使用Pomelo.EntityFrameworkCore.MySql)
- Microsoft.Extensions.DependencyInjection(用于依赖注入管理)
定义不同数据库的DbContext
首先定义两个实体类,分别对应两个数据库中的表:
// 业务数据库实体,对应MySQL中的User表
public class User
{
public int Id { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
}
// 日志数据库实体,对应SQL Server中的Log表
public class Log
{
public int Id { get; set; }
public string Content { get; set; }
public DateTime CreateTime { get; set; }
}
接下来分别定义两个DbContext,分别对应MySQL和SQL Server:
// MySQL数据库上下文
public class MySqlDbContext : DbContext
{
public DbSet<User> Users { get; set; }
public MySqlDbContext(DbContextOptions<MySqlDbContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// 配置User表映射
modelBuilder.Entity<User>().ToTable("User");
base.OnModelCreating(modelBuilder);
}
}
// SQL Server数据库上下文
public class SqlServerDbContext : DbContext
{
public DbSet<Log> Logs { get; set; }
public SqlServerDbContext(DbContextOptions<SqlServerDbContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// 配置Log表映射
modelBuilder.Entity<Log>().ToTable("Log");
base.OnModelCreating(modelBuilder);
}
}
配置依赖注入
在程序启动阶段,通过依赖注入注册两个DbContext,分别绑定对应的连接字符串和数据库驱动:
// 假设使用.NET Core的Web应用,在Program.cs中配置
var builder = WebApplication.CreateBuilder(args);
// 注册MySQL上下文,连接字符串从配置文件读取
builder.Services.AddDbContext<MySqlDbContext>(options =>
{
var mysqlConnection = builder.Configuration.GetConnectionString("MySql");
options.UseMySql(mysqlConnection, ServerVersion.AutoDetect(mysqlConnection));
});
// 注册SQL Server上下文,连接字符串从配置文件读取
builder.Services.AddDbContext<SqlServerDbContext>(options =>
{
var sqlServerConnection = builder.Configuration.GetConnectionString("SqlServer");
options.UseSqlServer(sqlServerConnection);
});
var app = builder.Build();
对应的配置文件appsettings.json中添加连接字符串:
{
"ConnectionStrings": {
"MySql": "Server=localhost;Database=test_mysql;Uid=root;Pwd=123456;",
"SqlServer": "Server=localhost;Database=test_sqlserver;Uid=sa;Pwd=123456;"
}
}
业务层调用示例
在业务服务中,通过构造函数注入需要的DbContext实例,即可操作对应的数据库:
public class UserService
{
private readonly MySqlDbContext _mySqlDbContext;
private readonly SqlServerDbContext _sqlServerDbContext;
// 注入两个上下文实例
public UserService(MySqlDbContext mySqlDbContext, SqlServerDbContext sqlServerDbContext)
{
_mySqlDbContext = mySqlDbContext;
_sqlServerDbContext = sqlServerDbContext;
}
// 操作MySQL数据库,新增用户
public async Task AddUserAsync(User user)
{
_mySqlDbContext.Users.Add(user);
await _mySqlDbContext.SaveChangesAsync();
}
// 操作SQL Server数据库,新增日志
public async Task AddLogAsync(Log log)
{
_sqlServerDbContext.Logs.Add(log);
await _sqlServerDbContext.SaveChangesAsync();
}
// 跨数据库查询示例,获取用户和对应的操作日志
public async Task<(User, List<Log>)> GetUserWithLogsAsync(int userId)
{
var user = await _mySqlDbContext.Users.FirstOrDefaultAsync(u => u.Id == userId);
// 假设日志中存储了用户ID关联,这里简化查询逻辑
var logs = await _sqlServerDbContext.Logs.Where(l => l.Content.Contains(userId.ToString())).ToListAsync();
return (user, logs);
}
}
动态切换同类型数据库
如果是同类型数据库(比如多个MySQL实例)需要动态切换,可以通过工厂模式实现,根据传入的数据库标识返回对应的DbContext:
public interface IDbContextFactory
{
MySqlDbContext CreateDbContext(string dbName);
}
public class MySqlDbContextFactory : IDbContextFactory
{
private readonly IConfiguration _configuration;
public MySqlDbContextFactory(IConfiguration configuration)
{
_configuration = configuration;
}
public MySqlDbContext CreateDbContext(string dbName)
{
// 根据dbName从配置中获取对应的连接字符串
var connectionString = _configuration.GetConnectionString(dbName);
var optionsBuilder = new DbContextOptionsBuilder<MySqlDbContext>();
optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
return new MySqlDbContext(optionsBuilder.Options);
}
}
使用时只需要传入对应的数据库名称即可获取对应的上下文:
public class DynamicDbService
{
private readonly IDbContextFactory _dbContextFactory;
public DynamicDbService(IDbContextFactory dbContextFactory)
{
_dbContextFactory = dbContextFactory;
}
public async Task AddUserToDbAsync(string dbName, User user)
{
using var dbContext = _dbContextFactory.CreateDbContext(dbName);
dbContext.Users.Add(user);
await dbContext.SaveChangesAsync();
}
}
注意事项
- 不同数据库的
DbContext不要混用,避免操作错误的数据库实例 - 连接字符串建议加密存储,避免敏感信息泄露
- 如果使用事务,跨数据库的事务需要使用分布式事务,EF默认不支持,需要额外配置
- 定期清理不再使用的
DbContext实例,避免内存泄漏
C#Entity_Framework多数据库切换数据源切换修改时间:2026-07-07 14:39:34