2009-06-25 38 views
5

Vì vậy, tại sao điều này không bao giờ thực hiện được với chức năng gọi lại?vấn đề truy vấn không đồng bộ hóa 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"; 
     } 
    } 
} 

}

Trả lời

3

Một số điểm tôi nhận thấy:

  1. Phương pháp callback được gọi là chỉ sau khi tôi loại bỏ các WAITFOR TRÌ HOÃN stmt.
  2. Không cần phải bỏ phiếu cho kết quả.Đã hoàn thành, vì phương thức gọi lại chỉ được kích hoạt sau khi hoàn tất quá trình xử lý không đồng bộ .
  3. Không cần đặt rõ ràng dr = null trong phần khác bởi vì theo mặc định, sẽ không có giá trị.
  4. Bạn nên xử lý InvalidOperationException và ArgumentException trong phương pháp HandleCallback .
  5. Trong gọi lại xử lý bất cứ khi nào, EndExecuteReader() được gọi là I tiếp tục nhận ngoại lệ "Hoạt động không đồng bộ đã hoàn tất ." Vì vậy, tôi đã không bao giờ có thể nhận được kết quả trong dr.

Nếu bạn đang gặp vấn đề được liệt kê ở điểm không. 5, bạn có thể sử dụng giải pháp thay thế sau được triển khai bằng cách sử dụng các đại biểu không đồng bộ thay vì được xây dựng trong BeginExecuteReader() và EndExecuteReader(). Trong giải pháp bên dưới, điều khiển sẽ ngay lập tức được trả về dòng tiếp theo sau khi ủy nhiệm được gọi, giống như nó xảy ra trong trường hợp của BeginExecuteReader().

Biện pháp thứ:

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

Đúng. # 5 là tùy chọn mà tôi đã sử dụng. :) Cảm ơn câu trả lời tuyệt vời! – bitcycle

+0

Đề cập đến không. Cảm ơn câu hỏi tuyệt vời: D –

3

Tôi nghĩ rằng kết nối đang được đóng trước khi Reader có thể làm việc ...

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

Hãy thử thay đổi nó để ...

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); 

Vào cách mã này chờ 3 phút? Bởi vì để tạm dừng trong 3 giây không nên WAITFOR DELAY '0: 0: 3'?

+0

Fredrik tôi đã thay đổi sự chậm trễ đến 0: 0: 5 và vẫn gọi tôi doesnt bị sa thải. Chỉ khi tôi loại bỏ sự chậm trễ waitfor stmt tôi có thể gỡ lỗi vào gọi lại. Bạn đã thử debuggin chưa? Nó khá thú vị. –

Các vấn đề liên quan