專案需支援多種資料庫,不想在程式碼中寫死 SqlConnection/OleDbConnection 等具體類別。.NET 內建 DbProviderFactory 抽象工廠,配合設定檔即可實現「只改設定、不改代碼」的資料庫切換。
<connectionStrings>
<add name="SqlConn" connectionString="server=.;uid=sa;pwd=123;db=Test" providerName="System.Data.SqlClient" />
<add name="OleDbConn" connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=test.mdb" providerName="System.Data.OleDb" />
</connectionStrings>
using System;
using System.Data;
using System.Data.Common;
using System.Configuration;
class DataBaseFac
{
private DbConnection cnn;
private DbCommand cmd;
private DbProviderFactory provider;
public DataBaseFac(string connName = "SqlConn")
{
// 1. 取得 ProviderName
string providerName = ConfigurationManager.ConnectionStrings[connName].ProviderName;
// 2. 取得對應工廠
provider = DbProviderFactories.GetFactory(providerName);
// 3. 建立連線、命令物件
cnn = provider.CreateConnection();
cnn.ConnectionString = ConfigurationManager.ConnectionStrings[connName].ConnectionString;
cmd = provider.CreateCommand();
cmd.Connection = cnn;
}
// 執行查詢回傳 DataTable
public DataTable ExecuteQuery(string sql)
{
DataTable dt = new DataTable();
DbDataAdapter adapter = provider.CreateDataAdapter();
cmd.CommandType = CommandType.Text;
cmd.CommandText = sql;
adapter.SelectCommand = cmd;
try
{
cnn.Open();
adapter.Fill(dt);
}
catch { dt = null; }
finally { cnn.Close(); }
return dt;
}
// 執行非查詢
public int ExecuteNonQuery(string sql)
{
cmd.CommandText = sql;
try
{
cnn.Open();
return cmd.ExecuteNonQuery();
}
finally { cnn.Close(); }
}
}
providerName。DbConnection, DbCommand, DbDataAdapter 抽象基類。cmd.Parameters.Add(provider.CreateParameter())。ExecuteScalar, ExecuteReader 等常用方法。DbTransaction)。appSettings 或自訂 ConfigurationSection 管理多連線字串。有人用
switch(providerName)new 具體 Connection/Command,自稱「工廠模式」。這違背工廠模式初衷——工廠模式正是為了消除 switch/case。正確做法正是DbProviderFactories.GetFactory()。
DbProviderFactory 是 .NET 早期內建的抽象工廠典範。雖然現代 ORM (EF Core, Dapper) 已大幅簡化資料存取,但理解此機制有助於維護舊系統、撰寫跨資料庫工具或實作輕量級 Micro-ORM。