所有 SQL Server 資料存取 API (ODBC、OLE DB、ADO、SqlClient) 均提供連線與要求的抽象。SQL Server 2000 限制單一連線同一時間僅能有一個待處理要求,常以伺服器端游標繞過限制。SQL Server 2005 引入 MARS (Multiple Active Result Sets),解除此限制,允許單一連線同時擁有多個作用中的結果集。
SqlConnection / SQL_HANDLE_DBCSqlCommand / SQL_HANDLE_STMTSELECT/FETCH 產生資料列,以「預設結果集」 (Default Result Set) 流式傳輸至用戶端。情境:鬆散耦合的清單處理系統,使用 Operations 資料表作為佇列。應用程式需:
在 SQL Server 2000,步驟 1 的讀取游標開啟期間,無法在同一連線上執行步驟 2 的業務邏輯,必須開啟第二個連線或使用伺服器端游標,增加資源消耗與程式複雜度。
SqlCommand 物件處於執行狀態。SqlDataReader 期間,於同一連線發出新命令 (INSERT/UPDATE/SELECT)。MultipleActiveResultSets=True (預設關閉)。string connStr = "Server=.;Database=Test;Integrated Security=True;MultipleActiveResultSets=True";
using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open();
SqlCommand cmdQueue = new SqlCommand("SELECT TOP 1 OpId, OpCode FROM Operations WHERE Processed=0", conn);
SqlDataReader reader = cmdQueue.ExecuteReader();
while (reader.Read())
{
int opId = reader.GetInt32(0);
string opCode = reader.GetString(1);
// 同一連線、同一交易內執行業務邏輯
using (SqlTransaction tx = conn.BeginTransaction())
{
try
{
SqlCommand cmdBiz = new SqlCommand("EXEC ProcessOperation @OpCode", conn, tx);
cmdBiz.Parameters.AddWithValue("@OpCode", opCode);
cmdBiz.ExecuteNonQuery();
SqlCommand cmdUpdate = new SqlCommand("UPDATE Operations SET Processed=1 WHERE OpId=@Id", conn, tx);
cmdUpdate.Parameters.AddWithValue("@Id", opId);
cmdUpdate.ExecuteNonQuery();
tx.Commit();
}
catch
{
tx.Rollback();
throw;
}
}
}
reader.Close();
}
此範例展示在讀取佇列資料的同時,於同一連線內開啟交易執行業務邏輯與更新狀態,無需額外連線。