淺談多重作用結果集(Multiple Active Result Set,MARS)
MARS搭配SQL Server 2005以上的版本,讓前端的.NET程式可以在同一個連線中同時進行多個批次查詢。
- 下列程式示範未啟用MARS,因此會收到下圖的錯誤訊息。
 
1: SqlConnectionStringBuilder conbd = new SqlConnectionStringBuilder();
2: conbd.InitialCatalog = "Northwind";
3: conbd.IntegratedSecurity = true;
4: conbd.DataSource = ".";
5: using (SqlConnection con = new SqlConnection(conbd.ToString()))
   6:  {                
	7: if (con.State != ConnectionState.Open) con.Open();
8: try
   9:      {
	10: using (TransactionScope trans = new TransactionScope())
  11:          {
	12: using (SqlCommand cmd = new SqlCommand("select c1,c2 from t1", con))
  13:              {
	14: using (SqlDataReader reader = cmd.ExecuteReader())
  15:                  {
	16: while (reader.Read())
  17:                      {
	18: using (SqlCommand cmdInsert = new SqlCommand("insert into t2 values(@c1,@c2)", con))
  19:                          {
	
  20:                              cmdInsert.Parameters.Clear();
	21: cmdInsert.Parameters.AddRange(new SqlParameter[] { new SqlParameter("@c1", SqlDbType.Int), new SqlParameter("@c2", SqlDbType.VarChar, 10) });
  22:                              cmdInsert.Parameters[0].Value = reader[0];
	
  23:                              cmdInsert.Parameters[1].Value = reader[1];
	
  24:                              cmdInsert.ExecuteNonQuery();
	
  25:                          }
	
  26:                      }
	
  27:                  }
	28: cmd.CommandText = "delete from t1";
  29:                  cmd.ExecuteNonQuery();
	
  30:              }                        
	
  31:              trans.Complete();
	
  32:          }
	
  33:      }
	34: catch (Exception ex)
  35:      {
	
  36:          MessageBox.Show(ex.Message);
	
  37:      }
	
  38:  }
要解決上述問題,只要啟用MARS即可順利在同一個連線中從SqlDataReader讀出資料並新增和刪除資料(設定方式如下)。
1: conbd.MultipleActiveResultSets = true;
特別強調MARS是用在單一連線上建立邏輯連接,來處理多個SQL命令,以SqlClient為例,僅限於SqlConnection的共用,SqlCommand則必須各自宣告,否則會收到如下圖的錯誤訊息。
- 下列程式嘗試於開啟MARS後共用相同sqlCommand物件來同時處理SqlDataReader及進行Insert動作,在SqlDataReader尚未關閉前,執行ExecuteNonQuery方法將會發生例外。
 
1: SqlConnectionStringBuilder conbd = new SqlConnectionStringBuilder();
2: conbd.InitialCatalog = "Northwind";
3: conbd.IntegratedSecurity = true;
4: conbd.DataSource = ".";
5: conbd.MultipleActiveResultSets = true;
6: using (SqlConnection con = new SqlConnection(conbd.ToString()))
   7:  {                
	8: if (con.State != ConnectionState.Open) con.Open();
9: try
  10:      {
	11: using (TransactionScope trans = new TransactionScope())
  12:          {
	13: using (SqlCommand cmd = new SqlCommand("select c1,c2 from t1", con))
  14:              {
	15: using (SqlDataReader reader = cmd.ExecuteReader())
  16:                  {
	17: while (reader.Read())
  18:                      {                                  
	19: cmd.CommandText = "insert into t2 values(@c1,@c2)";
  20:                          cmd.Parameters.Clear();
	21: cmd.Parameters.AddRange(new SqlParameter[] { new SqlParameter("@c1", SqlDbType.Int), new SqlParameter("@c2", SqlDbType.VarChar, 10) });
  22:                          cmd.Parameters[0].Value = reader[0];
	
  23:                          cmd.Parameters[1].Value = reader[1];
	
  24:                          cmd.ExecuteNonQuery();
	
  25:                      }
	
  26:                  }
	27: cmd.CommandText = "delete from t1";
  28:                  cmd.ExecuteNonQuery();
	
  29:              }                        
	
  30:              trans.Complete();
	
  31:          }
	
  32:      }
	33: catch (Exception ex)
  34:      {
	
  35:          MessageBox.Show(ex.Message);
	
  36:      }
	
  37:  }
參考資料: