ADO.NET的异步执行命令

在 2.0 以前的版本中 , 通常为每个数据库服务器的请求打开和关闭一个连接 ,  并且同时只能执行一条命令 , 也就是不支持异步进程 。

使用 ADO.NET 2.0 的异步进程 ,  数据库连接字符串要添加 Asynchronous Processing=true

如果执行多条命令连接字符串还要添加 MultipleActiveResultSets=true

这里使用的数据库及表为  MS Sql Server 2000 的 NorthWind 的 Customers 表 和 Orders 表 ,  页面上只需拖放相应的GridView 控件。
先看看异步回调 , 这里只执行一条命令 :

string strSelectCmdOrders = @"SELECT TOP 5 C.CustomerID,CompanyName,ContactName,
                 OrderID,OrderDate,ShipCity
FROM Customers C ,Orders O WHERE C.CustomerID = O.CustomerID
ORDER BY CompanyName,ContactName
";
//以此变量判断异步执行是否完成
bool isComplete = false;

protected void Page_Load(object sender, EventArgs e)
{
if ( !IsPostBack )
{
SqlConnection sqlCon
=
        new
SqlConnection
       (
@"Data Source=.;Initial Catalog=NorthWind;
        Integrated Security=True;Asynchronous Processing=true
" );
SqlCommand sqlCmdOrders
= new SqlCommand( strSelectCmdOrders , sqlCon );
sqlCon.Open( );
sqlCmdOrders.BeginExecuteReader(
new AsyncCallback( callBackOrders ) ,
        sqlCmdOrders , CommandBehavior.CloseConnection );
//如果异步执行完成则结束该事件处理
while ( !isComplete )
{
System.Threading.Thread.Sleep(
1 );
}
}
}

private void callBackOrders ( IAsyncResult asyncResult )
{
using ( SqlCommand sqlCmdOrders = asyncResult.AsyncState as SqlCommand )
{
using ( SqlDataReader sqlReader = sqlCmdOrders.EndExecuteReader( asyncResult ) )
{
GridViewOrders.DataSource
= sqlReader;
GridViewOrders.DataBind( );
isComplete
= true;
}
}
}
注意 BeginExecuteReader 方法的第2个参数 , 该参数接收一个传递给回调方法的定制对象 , 在回调方法里可以通过 AsyncState 获取该对象
通过跟踪程序 结合使用 SQL SERVER 事件探察器发现在调用 BeginExecuteReader 方法时执行了 SQL 语句.
再来看看 MARS 和 异步处理的结合:
string strSelectCmdOrders = @"SELECT TOP 5 C.CustomerID,CompanyName,ContactName,
OrderID,OrderDate,ShipCity
FROM Customers C ,Orders O WHERE C.CustomerID = O.CustomerID
AND CompanyName = 'Alfreds Futterkiste'
ORDER BY CompanyName,ContactName
";
string strSelectCmdCustomers = "SELECT * FROM Customers WHERE CompanyName = 'Alfreds Futterkiste'";

protected void Page_Load(object sender, EventArgs e)
{
if ( !IsPostBack )
{
using ( SqlConnection sqlCon =
        new
SqlConnection( @"Data Source=.;Initial Catalog=NorthWind;Integrated Security=True;
          Asynchronous Processing=true;MultipleActiveResultSets=true
" ) )
{
sqlCon.Open( );

SqlCommand sqlCmdCustomer
= new SqlCommand( strSelectCmdCustomers , sqlCon );
IAsyncResult asyncResultCustomer
= sqlCmdCustomer.BeginExecuteReader( );

SqlCommand sqlCmdOrder
= new SqlCommand( strSelectCmdOrders , sqlCon );
IAsyncResult asyncResultOrder
= sqlCmdOrder.BeginExecuteReader( );

System.Threading.WaitHandle waitHandleCustomer
=
                asyncResultCustomer.AsyncWaitHandle;
System.Threading.WaitHandle waitHandleOrder
=
                asyncResultOrder.AsyncWaitHandle;
System.Threading.WaitHandle[] waitHandles
=
          
new System.Threading.WaitHandle[] { waitHandleCustomer , waitHandleOrder };

for ( int i = 0 ; i < waitHandles.Length ; i++ )
{
switch ( System.Threading.WaitHandle.WaitAny( waitHandles ) )
{
case 0:
SqlDataReader sqlReaderCustomer
=
                  sqlCmdCustomer.EndExecuteReader( asyncResultCustomer );
GridView1.DataSource
= sqlReaderCustomer;
GridView1.DataBind( );
break;
case 1:
SqlDataReader sqlReaderOrder
=
                  sqlCmdOrder.EndExecuteReader( asyncResultOrder );
GridView2.DataSource
= sqlReaderOrder;
GridView2.DataBind( );
break;
}
}
sqlCmdCustomer.Dispose( );
sqlCmdOrder.Dispose( );
}
}

}

注意这里的数据库连接字符串加上了 MultipleActiveResultSets=true  , 还有点是这个功能目前只支持 MS SQL SERVER 2005 及以上版本
如果要取消异步进程 ,  则只需在调用相应的 Command 对象的 Cancel 方法 , 如果想要 Rollback 已由 Command 对象完成的处理 , 则在执行命令前提供一个定制事务 .
可以看出 MARS 和异步命令处理一起使用是很强大的~

修改了部分的原文:http://blog.csdn.net/web718/archive/2009/04/17/4086462.aspx

posted on 2011-03-28 15:35  Scarface  阅读(1630)  评论(0编辑  收藏  举报

导航