2009-06-25 6 views
5

それでは、なぜこれがコールバック関数になっていないのですか?sql非同期クエリの問題

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Data.SqlClient; 

namespace sqlAsyncTesting { 
    public partial class Form1 : Form { 

    public Form1() { 
     InitializeComponent(); 
    } 

    private void button1_Click(object sender, EventArgs e) { 
     using (SqlConnection conn = new SqlConnection(@"Data Source = bigapple; Initial Catalog = master; Integrated Security = SSPI; Asynchronous Processing = true;")) { 
      conn.Open(); 
      SqlCommand cmd = new SqlCommand(@"WAITFOR DELAY '00:03'; Select top 3 * from sysobjects;", conn); 
      IAsyncResult result = cmd.BeginExecuteReader(new AsyncCallback(HandleCallback), cmd, CommandBehavior.CloseConnection); 
     } 
    } 

    private void HandleCallback(IAsyncResult result) { 
     SqlDataReader dr; 
     SqlCommand _this = (SqlCommand)result.AsyncState; 

     if (result.IsCompleted) { 
      dr = _this.EndExecuteReader(result); 
     } else dr = null; 

     DataTable dt = new DataTable(); 
     DataSet ds = new DataSet(); 

     dt.Load(dr); 
     ds.Tables.Add(dt); 
     dr.Close(); 
     Complete(ds); 
    } 

    private void Complete(DataSet ds) { 
     string output = string.Empty; 
     foreach (DataColumn c in ds.Tables[0].Columns) { 
      output += c.ColumnName + "\t"; 
     } 
     output += "\r\n"; 
     foreach (DataRow dr in ds.Tables[0].Rows) { 
      foreach (object i in dr.ItemArray) { 
       output += i.ToString() + "\t"; 
      } 
      output += "\r\n"; 
     } 
    } 
} 

}私はリーダーが仕事ができる前に、接続が閉じられていると思う

答えて

3

いくつかのポイント:

  1. は、コールバックメソッドは、私はWAITFOR DELAY のstmtを取り除いた後にのみ呼ばれていました。
  2. 非同期処理が完了した後に初めて コールバックメソッドが起動されるため、結果をポーリングする必要はありません。完了しました。
  3. デフォルトでは がnullになるため、else部分にdr = nullを明示的に設定する必要はありません。
  4. HandleCallbackメソッドでInvalidOperationExceptionと ArgumentExceptionを処理する必要があります。
  5. いつでもハンドルコールバックで、EndExecuteReader()が呼び出されました。 " 非同期操作が既に完了しています が完了しました。だから私は決して の結果を得ることができませんでした。

ポイントナンバーに記載されている問題に直面している場合は、 5では、組み込みのBeginExecuteReader()およびEndExecuteReader()ではなく、非同期デリゲートを使用して実装された次の代替ソリューションを使用できます。以下のソリューションでも、BeginExecuteReader()の場合と同じように、コントロールはデリゲートが呼び出された直後に次の行に戻されます。

代替ソリューション:0:

public partial class Form2 : Form 
{ 
    public Form2() 
    { 
     InitializeComponent(); 
    } 

    private delegate DataSet GetDSDelegate(string query); 

    private void button1_Click(object sender, EventArgs e) 
    { 
     GetDSDelegate del = new GetDSDelegate(GetDataSetAsync); 
     del.BeginInvoke(@"Select top 3 * from table1;", null, null); 
    } 

    private DataSet GetDataSetAsync(string query) 
    { 
     DataSet ds; 
     using (SqlConnection conn = new SqlConnection(@"Data Source = mmmmm000011\sqlexpress; Initial Catalog = SOExamples; Integrated Security = SSPI; Asynchronous Processing = true;")) 
     using (SqlCommand cmd = new SqlCommand(query, conn)) 
     { 
      try 
      { 
       conn.Open(); 
       SqlDataReader dr = cmd.ExecuteReader(); 

       DataTable dt = new DataTable(); 
       ds = new DataSet(); 

       dt.Load(dr); 
       ds.Tables.Add(dt); 
       dr.Close(); 
       Complete(ds); 
      } 
      finally 
      { 
       if (conn.State != ConnectionState.Closed) 
        conn.Close(); 
      } 
     } 
     MessageBox.Show("Done!!!"); 
     return ds; 
    } 

    private void Complete(DataSet ds) 
    { 
     ... 
    } 
} 
+0

#5は私が使い終わったオプションでした。 :)偉大な答えをありがとう! – bitcycle

+0

記載されていません。大きな質問ありがとう:D –

3

...

using (SqlConnection conn = new SqlConnection(@"Data Source = bigapple; Initial Catalog = master; Integrated Security = SSPI; Asynchronous Processing = true;")) 

にそれを変更してみてください...デベロッパー

SqlConnection conn = new SqlConnection(@"Data Source = bigapple; Initial Catalog = master; Integrated Security = SSPI; Asynchronous Processing = true;"); 
     conn.Open(); 
     SqlCommand cmd = new SqlCommand(@"WAITFOR DELAY '00:03'; Select top 3 * from sysobjects;", conn); 
     IAsyncResult result = cmd.BeginExecuteReader(new AsyncCallback(HandleCallback), cmd, CommandBehavior.CloseConnection); 

このコードは3分待っていますか? WAITFOR DELAY '0:0:3'ではなく、3秒間停止する必要がありますか?私が気づい

+0

フレドリック私は0に遅延を変え5とまだ私のコールバックdoesntのはクビ。 waitfor delay stmtを削除したときだけ、コールバックにデバッグすることができます。デバッグを試しましたか?非常に興味深い。 –