支持异步处理的提供程序有 System.Data.SqlClient在针对大批量数据插入过更新时,使用异步处理方法可以不用等待多有数据更新完毕才能操作或者进行下步处理,改善了用户体验 SqlCommand对象方法如下:
异步方法 BeginExecuteNonQuery EndExecuteNonQuery
BeginExecuteXmlReader EndExecuteXmlReader
BeginExecuteReader EndExecuteReader
begin前缀的方法传入参数,end前缀的方法返回输出参数和返回值
begin前缀方法返回的是IAsyncResult 用于追踪一步方法的执行状态
IAsyncResult .AsnycState 用户自定义的状态对象
IAsyncResult .AsnycWaitHandle 呼叫代码的等待形式,是等其中的一个异步方法完成还是全部完成
IAsyncResult .CompletedSynchronously 获取所有异步方法是否同时完成
IAsyncResult .Iscompleted 是否执行完毕,可以根据此属性进行下部动作
在连接字符串中加入"async=true"
如果所有的命令都是同步的建议在连接字符串中显施加入"async=false"
如果有一部分命令是异步执行,又有一部分是同步同步执行,建议分别建立两个连接对象
如果"async=true"时,也可以执行同步命令,但是会损失一些资源
/**///// obtain connection strings from configuration files or
//// similar facility
//// NOTE: these connection strings have to include "async=true", for
//// example:
//// "server=myserver;database=mydb;integrated security=true;async=true"
//string connstrAccouting = GetConnString("accounting");
//string connstrHR = GetConnString("humanresources");
/**///// define two connection objects, one for each database
//using (SqlConnection connAcc = new SqlConnection(connstrAccounting))
//using (SqlConnection connHumanRes = new SqlConnection(connstrHR))
//{
// // open the first connection
// connAcc.Open();
// // start the execution of the first query contained in the
// // "employee_info" stored-procedure
// SqlCommand cmdAcc = new SqlCommand("employee_info", connAcc);
// cmdAcc.CommandType = CommandType.StoredProcedure;
// cmdAcc.Parameters.AddWithValue("@empl_id", employee_id);
// IAsyncResult arAcc = cmdAcc.BeginExecuteReader();
// // at this point, the "employee_info" stored-proc is executing on
// // the server, and this thread is running at the same time
// // now open the second connection
// connHumanRes.Open();
// // start the execution of the second stored-proc against
// // the human-resources server
// SqlCommand cmdHumanRes = new SqlCommand("employee_hrinfo",
// connHumanRes);
// cmdHumanRes.Parameters.AddWithValue("@empl_id", employee_id);
// IAsyncResult arHumanRes = cmdHumanRes.BeginExecuteReader();
// // now both queries are running at the same time
// // at this point; more work can be done from this thread, or we
// // can simply wait until both commands finish - in our case we'll
// // wait
// SqlDataReader drAcc = cmdAcc.EndExecuteReader(arAcc);
// SqlDataReader drHumanRes = cmdHumanRes.EndExecuteReader(arHumanRes);
// // now we can render the results, for example, bind the readers to an ASP.NET
// // web control, or scan the reader and draw the information in a
// // WebForms form.
//}
string custid = "ALFKI";
string orderid = "10643";
// NOTE: connection strings denoted by "connstring" have to include
// "async=true", for example:
string connstring = "server=(local);database=northwind;integrated security=true;async=true";
// we'll use three connections for this
using (SqlConnection c1 = new SqlConnection(connstring))
using (SqlConnection c2 = new SqlConnection(connstring))
using (SqlConnection c3 = new SqlConnection(connstring))
{
// get customer info
c1.Open();
SqlCommand cmd1 = new SqlCommand(
"SELECT CustomerID, CompanyName, ContactName FROM Customers WHERE CustomerID=@id", c1);
cmd1.Parameters.Add("@id", SqlDbType.Char, 5).Value = custid;
IAsyncResult arCustomer = cmd1.BeginExecuteReader();
// get orders
c2.Open();
SqlCommand cmd2 = new SqlCommand("SELECT * FROM Orders WHERE CustomerID=@id", c2);
cmd2.Parameters.Add("@id", SqlDbType.Char, 5).Value = custid;
IAsyncResult arOrders = cmd2.BeginExecuteReader();
// get order detail if user picked an order
IAsyncResult arDetails = null;
SqlCommand cmd3 = null;
if (null != orderid)
{
c3.Open();
cmd3 = new SqlCommand("SELECT * FROM [Order Details] WHERE OrderID=@id", c3);
cmd3.Parameters.Add("@id", SqlDbType.Int).Value = int.Parse(orderid);
arDetails = cmd3.BeginExecuteReader();
}
// build the wait handle array for WaitForMultipleObjects
WaitHandle[] handles = new WaitHandle[null == arDetails ? 2 : 3];
handles[0] = arCustomer.AsyncWaitHandle;
handles[1] = arOrders.AsyncWaitHandle;
if (null != arDetails)
handles[2] = arDetails.AsyncWaitHandle;
// wait for commands to complete and render page controls as we
// get data back
SqlDataReader r;
DataTable dt;
for (int results = (null == arDetails) ? 1 : 0; results < 3; results++)
{
// wait for any handle, then process results as they come
int index = WaitHandle.WaitAny(handles, 5000, false); // 5 secs
if (WaitHandle.WaitTimeout == index)
throw new Exception("Timeout");
switch (index)
{
case 0: // customer query is ready
r = cmd1.EndExecuteReader(arCustomer);
if (!r.Read())
continue;
lblCustomerID.Text = r.GetString(0);
lblCompanyName.Text = r.GetString(1);
lblContact.Text = r.GetString(2);
r.Close();
break;
case 1: // orders query is ready
r = cmd2.EndExecuteReader(arOrders);
dt = new DataTable();
dt.Load(r);
dgOrders.DataSource = dt; // data-bind to the orders grid
dgOrders.Refresh();
r.Close();
break;
case 2: // details query is ready
r = cmd3.EndExecuteReader(arDetails);
dt = new DataTable();
dt.Load(r);
dgDetails.DataSource = dt; // data-bind to the details grid
dgDetails.Refresh();
r.Close();
break;
}
}
}