C# 如何異步查詢數據庫


      以前在學習Socket的時候,經常會使用到異步操作,孰不知將異步用到數據庫查詢上也是一把利器,特別是在大數據量查詢的時候效果應該是比較明顯的。我順便寫了一個小例子,供大家參考。

      我們平時默認使用的查詢是同步的,也就是說一方不等待另一方做好准備,當查詢時間過長時,客戶端會被一直阻塞在這里而不能做其他事情。而當我們使用異步時,程序並不會阻塞或掛起線程,它會通過一個代理的回調方法完成查詢,主線程將會繼續執行,這樣便解決了同步所不能做到的並行執行的結果。

  代碼如下所示:

  

 1 public partial class AsyncSearchForm : Form
2 {
3 #region --Delegates--
4 private delegate void DisplayTimeInfoDelegate(string text);
5 private delegate void DisplayDataGridViewDelegate(DataTable myTable);
6 private delegate void DisplayInfoDelegate(string text);
7 #endregion
8
9 #region --Fields--
10 private SqlConnection mConnection;
11 private Stopwatch mWatch;
12 private DisplayTimeInfoDelegate myTimeDelegate;
13 private DisplayDataGridViewDelegate myDataDelegate;
14 #endregion
15
16 #region --Constructor--
17 public AsyncSearchForm()
18 {
19 InitializeComponent();
20 mWatch = new Stopwatch();
21 myDataDelegate = new DisplayDataGridViewDelegate(DisplayDataResults);
22 myTimeDelegate = new DisplayTimeInfoDelegate(DisplayTimeResults);
23 button_DoSearch.Click += new EventHandler(Button_DoSearch_Click);
24 }
25 #endregion
26
27 #region --Event Methods--
28 /// <summary>
29 /// 當點擊執行查詢時發生
30 /// </summary>
31 private void Button_DoSearch_Click(object sender, EventArgs e)
32 {
33 Application.DoEvents();
34 string connectionString = @"Data Source=127.0.0.1;Integrated Security=SSPI;Database=Northwind;Asynchronous Processing=true";
35 mConnection = new SqlConnection(connectionString);
36 string sqlString = "select * from Orders";
37 SqlCommand command = new SqlCommand(sqlString, mConnection);
38 mConnection.Open();
39 mWatch.Start();
40 AsyncCallback callBack = new AsyncCallback(HandleCallback);//注冊回調方法
41 //開始執行異步查詢,將Command作為參數傳遞到回調函數以便執行End操作
42 command.BeginExecuteReader(callBack, command);
43 }
44 #endregion
45
46 #region --Private Methods--
47 /// <summary>
48 /// 異步查詢的回調方法
49 /// </summary>
50 /// <param name="MyResult">異步操作狀態</param>
51 private void HandleCallback(IAsyncResult MyResult)
52 {
53 try
54 {
55 SqlCommand command = (SqlCommand)MyResult.AsyncState;
56 SqlDataReader reader = command.EndExecuteReader(MyResult);
57 mWatch.Stop();
58 string callBackTime = mWatch.ElapsedMilliseconds.ToString() + "毫秒";
59 DataTable dataTable = new DataTable();
60 dataTable.Load(reader);
61 this.Invoke(myTimeDelegate, callBackTime);
62 this.Invoke(myDataDelegate, dataTable);
63 }
64 catch (Exception MyEx)
65 {
66 this.Invoke(new DisplayInfoDelegate(DisplayTimeResults), String.Format(MyEx.Message));
67 }
68 finally
69 {
70 if (mConnection != null)
71 {
72 mConnection.Close();
73 }
74 }
75 }
76
77 /// <summary>
78 /// 在Label上顯示信息
79 /// </summary>
80 /// <param name="text"></param>
81 private void DisplayTimeResults(string text)
82 {
83 this.label_Time.Text = label_Time.Text + text;
84 }
85
86 /// <summary>
87 /// 綁定數據到DataGridView
88 /// </summary>
89 /// <param name="myTable"></param>
90 private void DisplayDataResults(DataTable myTable)
91 {
92 this.dgv_Data.DataSource = myTable;
93 }
94 #endregion
95 }

  運行結果如下所示:

  代碼很簡單,沒有很多的東西。數據庫我使用了Northwind,這次查詢用了4毫秒,在這樣短的查詢耗時下,異步對程序作用是不明顯的,真正使用時還需具體問題具體分析。需要提醒大家的是異步操作是普遍存在的,但異步方式也需要某種程度的協調,異步看似效率高無阻塞,但若程序在還沒得到查詢結果的時候就調用了使用查詢結果的方法就會出錯。因此還可以使用ManualResetEvent手動給線程指定阻塞和非阻塞的信號,這樣各個線程之間就可以等待彼此的信號達到同步目的,有興趣的朋友可以試試,我在這就不再贅述了。最后送大家一句話:“異步有風險,使用需謹慎。”


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM