FrameWork4.5 项目下使用EF6 同一项目操作多种数据库
本贴用于记录 EF6不通过配置文件去获取连接字符串也可以成功一个项目同时访问多种数据库的情况
项目下包含
// Contexts/BaseDbContext.cs
internal class BaseDbContext : DbContext
{
public BaseDbContext(string connectionString) : base(connectionString) { }
}
[DbConfigurationType(typeof(SqlServerDbConfiguration))]
internal class SqlServerContext : DbContext
{
static SqlServerContext() {
Console.WriteLine("SqlServerContext 静态构造函数已执行");
}
public SqlServerContext(string connectionString)
: base(EfConnectionHelper.CreateNamedConnectionString(
connectionString, "System.Data.SqlClient"))
{ }
//public SqlServerContext(string connectionString) : base(connectionString) { }
//public SqlServerContext() : base("name=SqlServerDbContext") { }
}
[DbConfigurationType(typeof(OracleDbConfiguration))]
internal class OracleContext : DbContext
{
static OracleContext() {
Console.WriteLine(" OracleContext 静态构造函数已执行");
}
public OracleContext(string connectionString)
: base(EfConnectionHelper.CreateNamedConnectionString(
connectionString, "Oracle.ManagedDataAccess.Client"))
{ }
//public OracleContext(string connectionString) : base(connectionString) { }
//public OracleContext() : base("name=OracleDbContext") { }
}
internal class SqliteContext : BaseDbContext
{
public SqliteContext(string connectionString) : base(connectionString) { }
}
// 定义配置类(保持不变)
internal class SqlServerDbConfiguration : DbConfiguration
{
public SqlServerDbConfiguration()
{
SetProviderServices("System.Data.SqlClient",
System.Data.Entity.SqlServer.SqlProviderServices.Instance);
SetDefaultConnectionFactory(new SqlConnectionFactory());
Console.WriteLine(" SqlServerDbConfiguration 已执行");
}
}
internal class OracleDbConfiguration : DbConfiguration
{
public OracleDbConfiguration()
{
SetProviderServices("Oracle.ManagedDataAccess.Client",
Oracle.ManagedDataAccess.EntityFramework.EFOracleProviderServices.Instance);
// Oracle 不需要默认连接工厂(通常由连接字符串决定)
Console.WriteLine(" OracleDbConfiguration 已执行");
}
}
public static class DatabaseFactory
{
public static IDatabaseService CreateService(DatabaseType dbType, string connectionString)
{
return new DatabaseService(dbType, connectionString);
}
public static IDatabaseService CreateService(string dbType, string connectionString)
{
// 添加参数验证
if (string.IsNullOrWhiteSpace(dbType))
throw new ArgumentException("数据库类型不能为空", nameof(dbType));
if (Enum.TryParse<DatabaseType>(dbType, true, out var type))
{
return CreateService(type, connectionString);
}
else
{
throw new ArgumentException($"不支持的数据库类型: {dbType}", nameof(dbType));
}
}
}
public interface IDatabaseService : IDisposable
{
DataTable ExecuteQuery(string sql, params object[] parameters);
int ExecuteNonQuery(string sql, params object[] parameters);
object ExecuteScalar(string sql, params object[] parameters);
}
// Services/DatabaseService.cs
public class DatabaseService : IDatabaseService
{
private readonly DatabaseType _dbType;
private readonly DbContext _context;
public DatabaseService(DatabaseType dbType, string connectionString)
{
switch (dbType)
{
case DatabaseType.SqlServer:
_context = new SqlServerContext(connectionString);
//_context = new SqlServerContext();
break;
case DatabaseType.Oracle:
_context = new OracleContext(connectionString);
//_context = new OracleContext();
break;
default:
throw new ArgumentException("不支持的数据库类型: " + dbType, "dbType");
}
// 调试:查看实际使用的提供程序
var providerName = _context.Database.Connection.GetType().FullName;
Console.WriteLine($"使用的数据库连接类型: {providerName}");
}
public DataTable ExecuteQuery(string sql, params object[] parameters)
{
var dataTable = new DataTable();
using (var command = _context.Database.Connection.CreateCommand())
{
command.CommandText = sql;
AddParameters(command, parameters);
if (_context.Database.Connection.State != ConnectionState.Open)
_context.Database.Connection.Open();
using (var reader = command.ExecuteReader())
{
dataTable.Load(reader);
}
}
return dataTable;
}
public int ExecuteNonQuery(string sql, params object[] parameters)
{
using (var command = _context.Database.Connection.CreateCommand())
{
command.CommandText = sql;
AddParameters(command, parameters);
if (_context.Database.Connection.State != ConnectionState.Open)
_context.Database.Connection.Open();
return command.ExecuteNonQuery();
}
}
public object ExecuteScalar(string sql, params object[] parameters)
{
using (var command = _context.Database.Connection.CreateCommand())
{
command.CommandText = sql;
AddParameters(command, parameters);
if (_context.Database.Connection.State != ConnectionState.Open)
_context.Database.Connection.Open();
return command.ExecuteScalar();
}
}
private void AddParameters(DbCommand command, object[] parameters)
{
if (parameters == null) return;
for (int i = 0; i < parameters.Length; i++)
{
var param = command.CreateParameter();
param.ParameterName = GetParameterName(i);
param.Value = parameters[i] ?? DBNull.Value;
command.Parameters.Add(param);
}
}
private string GetParameterName(int index)
{
switch (_dbType)
{
case DatabaseType.SqlServer: return $"@p{index}";
case DatabaseType.Oracle: return $":p{index}";
case DatabaseType.Sqlite: return $"@p{index}";
default: return $"@p{index}";
}
}
public void Dispose()
{
_context?.Dispose();
}
}
=====================================================
核心方法
public static class EfConnectionHelper
{
private static int _counter = 0;
public static string CreateNamedConnectionString(string connectionString, string providerInvariantName)
{
var name = $"DynamicConn_{Interlocked.Increment(ref _counter)}";
// 1. 动态添加到 ConfigurationManager.ConnectionStrings
var settings = ConfigurationManager.ConnectionStrings;
// 💥 关键:通过反射修改只读集合(.NET Framework 允许)
var readOnlyField = typeof(ConfigurationElementCollection)
.GetField("bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
if (readOnlyField != null)
{
readOnlyField.SetValue(settings, false);
}
settings.Add(new ConnectionStringSettings(name, connectionString, providerInvariantName));
return $"name={name}";
}
}
=====================================
使用
string connString = "";
using (var db = DatabaseFactory.CreateService(DatabaseType.SqlServer, connString))
{
var products = db.ExecuteQuery($@"
");
int count = products.Rows.Count;
// 处理数据...
}
string connString_Oracel = "";
using (var db = DatabaseFactory.CreateService(DatabaseType.Oracle, connString_Oracel))
{
var products = db.ExecuteQuery($@"
");
int count = products.Rows.Count;
// 处理数据...
}
浙公网安备 33010602011771号