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

Enterprise Library DAAB 在 TransactionScope 中連續執行 ExecuteReader 拋異常

     編輯:關於.NET

現象

同一 TransactionScope 內連續呼叫兩次 Database.ExecuteReader,第一條 SQL 故意非法(捕獲異常忽略),第二條合法,執行第二條時拋出:

InvalidOperationException: ExecuteReader requires an open and available Connection. The connection's current state is closed.

根因分析

DAAB 內部 ExecuteReader 邏輯(簡化):

public virtual IDataReader ExecuteReader(DbCommand command) {
    ConnectionWrapper wrapper = GetOpenConnection(false);
    try {
        PrepareCommand(command, wrapper.Connection);
        if (Transaction.Current != null)
            return DoExecuteReader(command, CommandBehavior.Default); // 共用連線,不自動關閉
        else
            return DoExecuteReader(command, CommandBehavior.CloseConnection);
    } catch {
        wrapper.Connection.Close(); // 異常時關閉連線
        throw;
    }
}

當環境異常(Transaction.Current != null)時,DAAB 共用同一 DbConnection 與 DbTransaction。第一次 ExecuteReader 發生異常進入 catch,連線被關閉。第二次嘗試使用同一已關閉連線,故失敗。

設計權衡探討

  • 微軟此設計或為確保異常時連線資源釋放,避免洩漏。
  • 但破壞了「同一 TransactionScope 內多次命令共用連線」的預期行為。
  • 開發者需自行決定:是拆分 TransactionScope、改用 ExecuteNonQuery 驗證、或捕獲異常後手動重新開啟連線(不推薦)。

建議應對策略

  1. 避免在同一 Transaction 中執行可能失敗的查詢後再執行後續查詢,將驗證性查詢移至 Transaction 之外。
  2. 若必須在同一 Transaction,考慮用 ExecuteNonQuery 或 ExecuteScalar 先檢查,或捕獲異常後 Transaction.Current 標記為 rollback 並重新開啟新 Transaction。
  3. 升級至較新版 Enterprise Library(6.x)或改用 Entity Framework / Dapper 等現代數據存取庫,它們對連線生命週期管理更合理。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved