避免每次使用 DAL 手動 new / Dispose,透過頁面基類 BasePage 在 OnInit 建立、OnUnload 釋放,實現類似靜態類的便利用法。
var dal = new DataAccessLayer(); → 易忘記 Dispose() 造成連線洩漏namespace MyProject.Common {
public class BasePage : System.Web.UI.Page {
// 公開 DAL 實例,衍生頁面直接使用 this.dal
public DataAccessLayer dal = new DataAccessLayer();
// 初始化:在 Page_Load 前執行
protected override void OnInit(EventArgs e) {
base.OnInit(e);
// 禁用快取,確保動態內容即時性
Response.Cache.SetNoStore();
}
// 釋放:頁面卸載時執行
protected override void OnUnload(EventArgs e) {
if (dal != null) {
dal.Dispose(); // 關閉連線、釋放資源
dal = null;
}
base.OnUnload(e);
}
}
}
public partial class UserList : BasePage {
protected void Page_Load(object sender, EventArgs e) {
if (!IsPostBack) {
// 直接使用 dal,無需實例化
DataTable dt = dal.RunSqlDataTable("SELECT * FROM Users WHERE IsActive = 1");
gvUsers.DataSource = dt;
gvUsers.DataBind();
}
}
protected void btnDelete_Click(object sender, EventArgs e) {
int id = Convert.ToInt32(((Button)sender).CommandArgument);
dal.RunSql("DELETE FROM Users WHERE ID = @id", new SqlParameter("@id", id));
// 重新繫結...
}
}
public class BaseHandler : IHttpHandler {
protected DataAccessLayer dal;
public void ProcessRequest(HttpContext context) {
dal = new DataAccessLayer();
try {
// 處理邏輯
} finally {
dal?.Dispose();
}
}
public bool IsReusable => false;
}
// ASP.NET Core / MVC 5+ with Autofac/Unity
public class UserController : Controller {
private readonly IDataAccessLayer _dal; // 介面注入
public UserController(IDataAccessLayer dal) {
_dal = dal;
}
// 無需手動 Dispose,容器管理生命週期 (Per Request)
}
public class DataAccessLayer : IDisposable {
private SqlConnection _conn;
private SqlTransaction _trans;
public DataAccessLayer() {
_conn = new SqlConnection(ConfigurationManager.ConnectionStrings["Default"].ConnectionString);
_conn.Open(); // 建構時開啟,或延遲到首次使用
}
public DataTable RunSqlDataTable(string sql, params SqlParameter[] parameters) {
using (var cmd = new SqlCommand(sql, _conn, _trans)) {
cmd.Parameters.AddRange(parameters);
var dt = new DataTable();
new SqlDataAdapter(cmd).Fill(dt);
return dt;
}
}
// ... 其他 RunSql 方法 ...
public void BeginTrans() { _trans = _conn.BeginTransaction(); }
public void CommitTrans() { _trans?.Commit(); _trans = null; }
public void RollbackTrans() { _trans?.Rollback(); _trans = null; }
public void Dispose() {
if (_trans != null) _trans.Dispose();
if (_conn != null) { _conn.Close(); _conn.Dispose(); }
}
}
SqlConnection 開啟/關閉會自動回收連線池,Dispose 必須呼叫OnUnload 即使發生未捕獲例外也會執行,保證釋放