在不重新編譯、重新部署的前提下,透過修改 Web.config 即可在 SQL Server 與 Oracle 之間無縫切換資料存取實作,符合「依賴抽象、開放封閉」原則。
+----------------+ 介面 IDAL +------------------+
| UI / BLL |------------------->| IDAL.GetDataSet |
+----------------+ +------------------+
^ ^
+--------+ +--------+
| |
+----------------+ +----------------+
| SQLHelper | | OracleHelper |
| (實作 IDAL) | | (實作 IDAL) |
+----------------+ +----------------+
// DBHelper 專案
namespace DBHelper
{
public interface IDAL
{
DataSet GetDataSet(string query);
}
}
using System.Data;
using System.Configuration;
using System.Data.OracleClient; // 或 Oracle.ManagedDataAccess.Client
namespace DBHelper
{
public class OracleHelper : IDAL
{
public DataSet GetDataSet(string query)
{
string connStr = ConfigurationManager.AppSettings["OracleConn"];
using (var conn = new OracleConnection(connStr))
using (var da = new OracleDataAdapter(query, conn))
{
var ds = new DataSet();
da.Fill(ds);
return ds;
}
}
}
}
using System.Data;
using System.Configuration;
using System.Data.SqlClient;
namespace DBHelper
{
public class SQLHelper : IDAL
{
public DataSet GetDataSet(string query)
{
string connStr = ConfigurationManager.AppSettings["SqlConn"];
using (var conn = new SqlConnection(connStr))
using (var da = new SqlDataAdapter(query, conn))
{
var ds = new DataSet();
da.Fill(ds);
return ds;
}
}
}
}
<appSettings>
<!-- 切換這裡即可:DBHelper.OracleHelper 或 DBHelper.SQLHelper -->
<add key="DataProvider" value="DBHelper.OracleHelper" />
<add key="OracleConn" value="Data Source=ORCL;User Id=app;Password=pwd;" />
<add key="SqlConn" value="Server=.;Database=TestDB;Uid=sa;Pwd=pwd;" />
</appSettings>
using System.Reflection;
using DBHelper;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// 從組態讀取完整型別名稱
string typeName = ConfigurationManager.AppSettings["DataProvider"];
// 載入組件並建立實例
IDal dal = (IDal)Assembly.Load("DBHelper").CreateInstance(typeName);
// 使用介面程式設計,完全不感知具體實作
DataSet ds = dal.GetDataSet("SELECT * FROM employees");
GridView1.DataSource = ds;
GridView1.DataBind();
}
}
若系統需同時存取多個資料庫,可將 IDAL 擴充為泛型或引入 Abstract Factory 模式:
public interface IDbFactory
{
IDal CreateDal(string dbKey); // dbKey 對應 config 區段
}
配合 connectionStrings 區段群組管理,達成「一個應用、多資料庫、零程式碼修改」。
| 優點 | 缺點/注意事項 |
|---|---|
| 零重新部署切換資料庫 | 反射建立實例有微小效能成本 (啟動時一次) |
| 符合 SOLID 原則,易測試、易維護 | 介面若變更需同步所有實作類別 |
| 新增資料庫只需加新類別、改 config | 複雜查詢 (Stored Procedure, Bulk Copy) 需擴充介面方法 |
「介面 + 反射 + 組態檔」是經典且輕量的策略模式落地,適合中小型專案快速支援多資料庫。大型系統建議導入完整 DI 容器 (Autofac, Unity, .NET Core 內建 DI) 管理生命週期與攔截器。