2011-01-20 68 views
2

更新我必須在我的問題中澄清一些事情嗎?我很驚訝地看到我在兩週內沒有得到任何評價,評論或答案。什麼時候SqlCommand.StatementCompleted應該觸發?


我想寫一個簡單的winforms應用程序,執行SQL SELECT語句異步。當sql服務器開始返回結果時,我想執行一個事件處理程序,它已連接到SqlCommand的StatementCompleted事件。

該表單包含兩個按鈕,一個文本框和一個標籤。當單擊button1時,我創建SqlCommand並連接事件處理程序,然後打開SqlConnection並調用BeginExecuteReader以啓動異步操作。我設置我的標籤以顯示命令正在執行。

在事件處理程序中,我只需設置標籤以顯示命令完成。

單擊按鈕2時,我更改標籤以顯示我們正在處理結果。然後我調用EndExecuteReader並將其返回值分配給一個新的SqlDataReader,然後再處理。

我看到的是,當命令準備就緒時,事件處理程序不會被調用。相反,當我的代碼完成處理由EndExecuteReader返回的閱讀器時,它會被調用。

我失去了一些東西在這裏?我是否誤解了事件的預期用途?我試圖找到一個StatementCompleted的例子,但我只能找到它的一般描述,沒有工作代碼。 SqlCommand.BeginExecuteReader page at MSDN上的示例使用循環並等待IAsyncResult.IsCompleted屬性爲true。我期望在該屬性成立的同時,StatementCompleted事件觸發。

public Form1() { 
    InitializeComponent(); 
} 

private IAsyncResult iAsyncResult; 
private SqlCommand sqlCommand; 

private void statementCompleted(object sender, 
           StatementCompletedEventArgs e) { 
    label1.Text = "Statement completed"; 
} 

private void button1_Click(object sender, EventArgs e) { 
    var northWindConnection = 
     new SqlConnection(
      "Data Source=.\\SqlExpress;Initial Catalog=Northwind;" + 
      "Integrated Security=True;" + 
      "asynchronous processing=true"); 
    sqlCommand = new SqlCommand("WAITFOR DELAY '00:00:05';" + 
           " SELECT * FROM [Order Details]", 
           northWindConnection); 
    sqlCommand.StatementCompleted += statementCompleted; 
    northWindConnection.Open(); 
    iAsyncResult = sqlCommand.BeginExecuteReader(); 
    label1.Text = "Executing"; 
} 

private void button2_Click(object sender, EventArgs e) { 
    label1.Text = "Not waiting anymore, reading"; 
    var results = new StringBuilder(); 
    var reader = sqlCommand.EndExecuteReader(iAsyncResult); 
    while (reader.Read()) { 
     for (int i = 0; i < reader.FieldCount; i++) { 
      results.Append(reader[i].ToString() + "\t"); 
     } 
     results.Append(Environment.NewLine); 
    } 
    reader.Close(); 
    sqlCommand.Connection.Close(); 
    textBox1.Text = results.ToString(); 
} 

回答

0

爲任何可能遇到此問題的人添加此信息,因爲在幾個月前沒有提供任何答案時提出這個問題。

StatementCompleted事件在對SqlCommand應用異步調用模式時無用。它確實被解僱了,但是隻在調用EndExecuteReader的時候才基本上太晚了。如果你想實現一般的異步調用模式,this MSDN article對如何完成它有一個很好的解釋。 BeginExecuteReader documentation中的示例代碼顯示了SqlCommand在異步模式下的正確用法。

+0

謝謝你第一個發表一個答案!調用EndExecuteReader時觸發StatementCompleted事件的事實是我在我的問題中已經提到的。你的答案似乎只是重複我發現的。是的,它確實觸發了,但只在EndExecuteReader上。是的,這意味着它沒有用。但是它在何處記載了直到EndExecuteReader纔會觸發StatementCompleted事件?該文檔僅聲明它在「執行Transact-SQL語句完成時」觸發。 – comecme 2011-04-26 20:51:10

2

事件的順序是這樣的:

  1. 呼叫SqlCommand.BeginExecuteReader(callback, stateObject)發送T-SQL到SQL Server和命令開始執行。
  2. 當數據是第一個可用的時,提供給BeginExecuteReader()AsyncCallback被調用。
  3. 該回調調用EndExecuteReader()以獲取對SqlDataReader對象的引用。
  4. 您使用SqlDataReader來讀取查詢的結果。這可能是一行或數百萬行。 直到返回所有請求的數據後,查詢才完成。
  5. 重複其他結果集(如果有)。
  6. 調用StatementCompleted事件 - 但前提是查詢/存儲過程不使用SET NOCOUNT ON

換句話說,StatementCompleted在T-SQL已完全完成(包括所有關聯的數據傳輸)時被調用。

相關問題