- ·上一篇文章:在.NET中使用脚本引擎
- ·下一篇文章:用多活动结果集优化ADO.NET2.0数据连接(1)
用多活动结果集优化ADO.NET2.0数据连接(2)
三、基于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便利了在同一个连接上的多重活动结果集的操作,但是在这些结果集上的操作仍然是串行运行的;如果你要求并行处理数据,那么多连接还是必需的。而且,请注意,一个使用了MARS功能的连接要比不使用的连接将利用更多些的资源。当然,从长远来看,你却节约了资源-由于你可以在同一个连接上执行多个命令;但是如果你在不需要的地方使用了MARS(也就是,如果你只需要单个结果集),你将会严重地影响系统性能。因此,如果你是在基于多数据库连接构建一个应用程序,那么你必须认真考虑哪些连接需要MARS,而哪些连接不需要-为了最大限度地利用资源。
总之,MARS是在ADO.NET中新增的一个非常优秀的功能-它允许你更高效地编写应用程序。欢迎使用MARS
做人要厚道,请注明转自chinazhan中国站长(www.ChinaZhan.com)。
本示例使用了随同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
做人要厚道,请注明转自chinazhan中国站长(www.ChinaZhan.com)。
