用多活動結果集最佳化ADO.NET2.0資料連線

來源:互聯網
上載者:User
ado|資料|最佳化

  閱讀概要 歡迎參予討論MARS的使用!通過這裡介紹的MARS技術上,你能夠在單個串連上執行多重資料庫查詢。而且依賴於MARS技術的編碼更為簡單易讀,並且使你在開發資料集中的Web應用程式時可以減少記憶體使用量並在一定程式上消除效能瓶頸。難道你不想嘗試一下MARS?

  多活動結果集(Multiple Active Result Sets,簡稱MARS)是ADO.NET 2.0的一個新特徵-它允許在單個串連上執行多重的資料庫查詢或預存程序。這樣的結果是,你能夠在單個串連上得到和管理多個、僅向前引用的、唯讀結果集。在MARS以前,針對每個結果集需要一個獨立的串連。當然,你還必須管理這些串連並且要付出相應的記憶體和潛在的應用程式中的高度擁擠的瓶頸代價-特別是在資料集中的Web應用程式中。

  第一個支援MARS的商務資料庫是SQL Server 2005,在本文中你將會詳細瞭解怎樣使用這一強有力的然而卻是易於添加到ADO.NET開發中去的工具。

  當在以前版本的SQL Server中存取資料結果集時,你需要建立額外的SqlConnection對象以配合使用SqlCommand。你需要追蹤你的所有結果集及其導致低效率程式的SqlConnections串連以及"There is already an open DataReader associated with this Connection"錯誤。現在,使用了MARS技術後,所有這些都成了過去。

  一、 準備工作

  最開始,你需要設定一新的連接字串以啟動多個活動串連。自然地,我們把這個設定命名為"MultipleActiveResultSets",並且如下使用之:

String connectionString = "Data Source=DBSERVER;" +
"Initial Catalog=AdventureWorlds;IntegratedSecurity=SSPI;" +
"MultipleActiveResultSets=True";


  它的預設設定是"False",並且你能明確地禁用它-如果你想傳遞"False"給這個MultipleActiveResultSets設定的話。

  請遵循下面步驟來建立和啟動MARS和ADO.NET 2.0:

  1. 建立一個如上面所示的連接字串。

  2. 建立一個SqlConnection對象並且用該連接字串初始化它。

  3. 使用它的Open()方法開啟這個SqlConnection對象。

  4. 對於你想要執行的每個查詢,建立一個新的SqlCommand對象。把它們與你在上面建立並開啟的SqlConnection對象相關聯。
 
  5. 使用適當的命令(如,如果你想讀該取查詢結果的話,可以使用ExecuteReader();或使用ExecuteNonQuery()來進行更新,等等)來執行查詢。

  6. 完成後,關閉SqlConnection對象。

  二、實戰

  在實際開發中普遍存在的一種典型的從資料庫中讀寫資料的情形是,你可以使用多重串連而現在只用一個串連就足夠了。例如,如果你有一些來自於幾個表中的資料-它們不能被連接到一個查詢中,那麼你就會有多重的串連-每個串連都有一個與之相關連的命令用於讀取資料。同樣,如果你正在向一個表寫資料,那麼你需要另外一個串連或串連集合-如果有多個表要被更新的話。

  可以考慮這樣的情形-你需要讀取來自兩個查詢A和B中的資料-從可能要寫向表C的資料擷取值,並且對你要寫向表D的行為保持一個審計記錄。在如此情形中,你的代碼可能如下:

  ·為A開啟一個串連

  ·執行查詢A,並且填充一個資料集

  ·為A關閉一個串連

  ·為B開啟一個串連

  ·執行查詢B,並且填充一個資料集

  ·為B關閉一個串連

  ·為C開啟一個串連

  ·為D開啟一個串連

  ·用從A和B中取得的詳細資料更新C

  ·用做過的審計標記更新D

  ·關閉D

  ·關閉C

  這是相當複雜的!

  當使用MARS時,你只要完成如下:

  ·用"MultipleActiveResultSets=true"開啟串連

  ·執行A並且填充一個資料集

  ·執行B並且填充一個資料集

  ·用從A和B中取得的詳細資料更新C

  ·用做過的審計標記更新D

  ·關閉串連

  更簡單!

  三、基於MARS和C#的樣本分析

  本樣本使用了隨同SQL Server 2005一起發行的AdventureWorks樣本資料庫,並且使用了該資料庫的開發版。注意,它還要改變該庫的一些欄位的內容,因此如果你想把這個樣本資料庫用於別的目的,請注意這一點。

  本樣本將展示怎樣從資料庫中讀取一個SalesOrder,然後減少已賣出的項目的庫存數額。典型地,這將要求建立到資料庫的兩個順序串連-一個用於讀取售出的項目數額,另一個用於使用減少的數額來更新庫存。

  下面的代碼片斷顯示了怎樣在不使用MARS功能的情況下達到這一目的。

ArrayList ids = new ArrayList();
ArrayList qtys = new ArrayList();
string connectionString = "Data Source=MEDIACENTER;" +
 "Initial Catalog=AdventureWorks;Integrated Security=SSPI;" +
 "MultipleActiveResultSets=False";
string strSQLGetOrder = "Select * from Sales.SalesOrderDetail" +
 "WHERE SalesOrderID = 43659";
SqlConnection readConnection = new SqlConnection(connectionString);
readConnection.Open();
SqlCommand readCommand =new SqlCommand(strSQLGetOrder, readConnection);
using (SqlDataReader rdr = readCommand.ExecuteReader()){
 while (rdr.Read()){
  ids.Add(rdr["ProductID"]);
  qtys.Add(rdr["OrderQty"]);
 }
}
readConnection.Close();
string strSQLUpdateInv = "UPDATE Production.ProductInventory " +
 "SET Quantity=Quantity-@amt WHERE (ProductID=@pid)";
SqlConnection writeConnection = new SqlConnection(connectionString);
writeConnection.Open();
SqlCommand writeCommand = new SqlCommand(strSQLUpdateInv,writeConnection);
writeCommand.Parameters.Add("@amt",SqlDbType.Int);
writeCommand.Parameters.Add("@pid",SqlDbType.Int);
for(int lp=0;lp<ids.Count;lp++){
 writeCommand.Parameters["@amt"].Value=qtys[lp];
 writeCommand.Parameters["@pid"].Value=ids[lp];
 writeCommand.ExecuteNonQuery();
}
writeConnection.Close();


  這個樣本從資料庫中讀取單個銷售訂單(這裡,訂單號43659被寫入程式碼)-該庫中有一項目列表。這些項目應該從庫存中扣除,而這是通過第二個串連完成的。然而,為了建立在第二個串連上的正確查詢-從相應的產品中扣除正確的數量-要求第一個查詢的結果在記憶體中被緩衝。並且在這個樣本中這是通過使用兩個數組列表來完成的。這裡的明顯耗費是:如果假定這是一個高度擁擠的網站,那麼我們需要大量的緩衝記憶體來處理這些最終要被扔掉的數值。

  為此,你還有另外一個方法-通過同時開啟兩個串連並且使用從一串連中讀取的資料結果-該串連被直接傳遞到在第二個串連上的更新命令;但是仍存在在開啟多個串連時記憶體和資料庫方面的代價。典型地,資料庫連接對於一個應用程式來說比記憶體具有更高的代價,所以這裡使用了順序串連方式。

  MARS提供瞭解決這個問題的在以上兩個方面均能達到最優的方法。你可以保持單個串連開啟著,從而減少了到資料庫的所有串連。這樣以來,你就不需要用一個記憶體變數來儲存讀取的結果。

  而且,該MARS代碼也為更短並且因此更易於讀取和維護。下面的代碼片斷展示了在相同的操作上使用MARS的情況:

string connectionString = "Data Source=MEDIACENTER;" +
 "Initial Catalog=AdventureWorks;Integrated Security=SSPI;" +
 "MultipleActiveResultSets=True";
string strSQLGetOrder = "Select * from Sales.SalesOrderDetail" +
 "WHERE SalesOrderID = 43659";
string strSQLUpdateInv = "UPDATE Production.ProductInventory " +
 "SET Quantity=Quantity-@amt WHERE (ProductID=@pid)";
SqlConnection marsConnection = new SqlConnection(connectionString);
marsConnection.Open();
SqlCommand readCommand = new SqlCommand(strSQLGetOrder, marsConnection);
SqlCommand writeCommand = new SqlCommand(strSQLUpdateInv, marsConnection);
writeCommand.Parameters.Add("@amt", SqlDbType.Int);
writeCommand.Parameters.Add("@pid", SqlDbType.Int);
using (SqlDataReader rdr = readCommand.ExecuteReader()){
 while (rdr.Read()){
  writeCommand.Parameters["@amt"].Value = rdr["OrderQty"];
  writeCommand.Parameters["@pid"].Value = rdr["ProductID"];
  writeCommand.ExecuteNonQuery();
 }
}
marsConnection.Close();


  正如你所見,這裡的方式在記憶體和資料庫連接方面比上一個樣本更易於讀取和管理且更為有效。並且,在這種情況中,唯讀取一次,隨後跟著的是寫操作;在某種典型情形下你的不使用MARS功能的代碼有可能更為複雜,並因此使得MARS為你帶來的節省更為明顯。

  儘管MARS便利了在同一個串連上的Multiple Active Result Set的操作,但是在這些結果集上的操作仍然是串列啟動並執行;如果你要求平行處理資料,那麼多串連還是必需的。而且,請注意,一個使用了MARS功能的串連要比不使用的串連將利用更多些的資源。當然,從長遠來看,你卻節約了資源-由於你可以在同一個串連上執行多個命令;但是如果你在不需要的地方使用了MARS(也就是,如果你只需要單個結果集),你將會嚴重地影響系統效能。因此,如果你是在基於多資料庫連接構建一個應用程式,那麼你必須認真考慮哪些串連需要MARS,而哪些串連不需要-為了最大限度地利用資源。

  總之,MARS是在ADO.NET中新增的一個非常優秀的功能-它允許你更高效地編寫應用程式。歡迎使用MARS!



相關文章

Cloud Intelligence Leading the Digital Future

Alibaba Cloud ACtivate Online Conference, Nov. 20th & 21st, 2019 (UTC+08)

Register Now >

Starter Package

SSD Cloud server and data transfer for only $2.50 a month

Get Started >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。