用多活动结果集优化ADO.NET2.0数据连接(2)
点击次数:19 次 发布日期:2008-11-26 14:15:36 作者:源代码网
|
源代码网推荐 源代码网推荐 本示例使用了随同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便利了在同一个连接上的多重活动结果集的操作,但是在这些结果集上的操作仍然是串行运行的;如果你要求并行处理数据,那么多连接还是必需的。而且,请注意,一个使用了MARS功能的连接要比不使用的连接将利用更多些的资源。当然,从长远来看,你却节约了资源-由于你可以在同一个连接上执行多个命令;但是如果你在不需要的地方使用了MARS(也就是,如果你只需要单个结果集),你将会严重地影响系统性能。因此,如果你是在基于多数据库连接构建一个应用程序,那么你必须认真考虑哪些连接需要MARS,而哪些连接不需要-为了最大限度地利用资源。 源代码网推荐 源代码网推荐 总之,MARS是在ADO.NET中新增的一个非常优秀的功能-它允许你更高效地编写应用程序。欢迎使用MARS 源代码网推荐 做人要厚道,请注明转自酷网动力(www.ASPCOOL.COM)。 源代码网推荐 源代码网供稿. |
