淺談多重作用結果集(Multiple Active Result Set,MARS)

淺談多重作用結果集(Multiple Active Result Set,MARS)

MARS搭配SQL Server 2005以上的版本,讓前端的.NET程式可以在同一個連線中同時進行多個批次查詢。

image

  • 下列程式示範未啟用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:  }

 

image

要解決上述問題,只要啟用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:  }

 

image

參考資料:

http://msdn.microsoft.com/zh-tw/library/h32h3abf.aspx