首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

解決「SqlTransaction 已完成,無法再使用」異常的正確事務處理模式

     編輯:關於SqlServer

此異常通常發生在嘗試重複使用已提交或已回滾的 SqlTransaction 物件時。正確做法是每個業務邏輯單元建立獨立事務,並在 try-catch-finally 區塊中確保妥善釋放。

標準單次事務範本

using (SqlConnection conn = new SqlConnection(connectionString))
{
    conn.Open();
    using (SqlTransaction trans = conn.BeginTransaction(IsolationLevel.ReadCommitted))
    {
        try
        {
            // 此處執行多條 SQL,共用同一事務
            ExecuteNonQuery(trans, "INSERT INTO StuInfo ...", parameters);
            ExecuteNonQuery(trans, "INSERT INTO StuSkill ...", parameters);

            trans.Commit();
            Console.WriteLine("資料寫入成功");
        }
        catch (Exception ex)
        {
            try { trans.Rollback(); } catch { /* 忽略回滾異常 */ }
            // 記錄錯誤、拋出或處理
            throw;
        }
    } // 自動 Dispose,釋放連線
}

關鍵要點

  1. 事務不可重用:Commit() 或 Rollback() 後,該 SqlTransaction 實例即失效,切勿再次呼叫。
  2. 使用 using 區塊:確保 SqlConnection、SqlTransaction、SqlCommand 正確釋放非受控資源。
  3. 隔離級別選擇:ReadCommitted 為預設且多數場景適用;高併發需考慮 Snapshot 或鎖提示。
  4. 參數化查詢:範例中省略參數綁定,實際開發務必使用參數防止 SQL 注入。

常見錯誤模式

' 錯誤:嘗試重用事務
trans.Commit();
trans.Commit(); ' 拋出「SqlTransaction 已完成」

' 錯誤:Catch 區塊未 Rollback 導致連線泄漏
catch (Exception ex) {
    // 忘記 Rollback,連線池中殘留未完成事務
}

進階:TransactionScope (推薦 .NET 2.0+)

using (var scope = new TransactionScope())
{
    using (var conn = new SqlConnection(connStr))
    {
        conn.Open();
        // 多條操作自動登記至環境事務
        ExecuteNonQuery(conn, "INSERT ...", params);
        ExecuteNonQuery(conn, "UPDATE ...", params);
    }
    scope.Complete(); // 無例外時提交
}

TransactionScope 支援分散式事務、自動管理連線登記,程式碼更簡潔安全。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved