首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> 關於ASP.NET

資料存取函數庫使用指南 (一):基類統一管理 DAL 實例生命週期

     編輯:關於ASP.NET

避免每次使用 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));
        // 重新繫結...
    }
}

進階:支援非 Page 類別 (Service/Handler)

public class BaseHandler : IHttpHandler {
    protected DataAccessLayer dal;
    
    public void ProcessRequest(HttpContext context) {
        dal = new DataAccessLayer();
        try {
            // 處理邏輯
        } finally {
            dal?.Dispose();
        }
    }
    public bool IsReusable => false;
}

更佳替代:Dependency Injection (現代架構)

// 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)
}
  • 基類模式適用於傳統 WebForms、快速原型、無 DI 容器環境
  • 新專案強烈建議導入 DI 容器,統一管理 DAL/Repository/Service 生命週期

DAL 實作關鍵點

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(); }
    }
}

注意事項

  • 執行緒安全:DAL 實例不可跨請求共用,基類模式確保每請求一實例
  • 連線池:SqlConnection 開啟/關閉會自動回收連線池,Dispose 必須呼叫
  • 例外處理:OnUnload 即使發生未捕獲例外也會執行,保證釋放
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved