SQL查询异步问题 [英] sql async query problem

查看:175
本文介绍了SQL查询异步问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

那么,为什么没有这个不断使它的回调函数?

 使用系统;
使用System.Collections.Generic;
使用System.ComponentModel;
使用System.Data这;
使用System.Drawing中;
使用System.Linq的;
使用System.Text;
使用System.Windows.Forms的;
使用System.Data.SqlClient的;命名空间sqlAsyncTesting {
    公共部分Form1类:表格{    公共Form1的(){
        的InitializeComponent();
    }    私人无效的button1_Click(对象发件人,EventArgs的发送){
        使用(SqlConnection的康恩=新的SqlConnection(@数据源= bigapple;初始目录=主;集成安全性= SSPI;异步处理=真;)){
            conn.Open();
            CMD的SqlCommand =新的SqlCommand(@WAITFOR DELAY '00:03';选择顶层3 *从系统对象;,康恩);
            IAsyncResult的结果= cmd.BeginExecuteReader(新的AsyncCallback(HandleCallback),CMD,CommandBehavior.CloseConnection);
        }
    }    私人无效HandleCallback(IAsyncResult的结果){
        SqlDataReader的博士;
        的SqlCommand _this =(的SqlCommand)result.AsyncState;        如果(result.IsCompleted){
            博士= _this.EndExecuteReader(结果);
        }其他博士= NULL;        DataTable的DT =新的DataTable();
        DataSet的DS =新的DataSet();        dt.Load(DR);
        ds.Tables.Add(DT);
        dr.Close();
        完整(DS);
    }    私人无效完成(DataSet的DS){
        字符串输出=的String.Empty;
        的foreach(在ds.Tables [0] .Columns的DataColumn C){
            输出+ = c.ColumnName +\\ t的;
        }
        输出+ =\\ r \\ n;
        的foreach(在ds.Tables [0] .Rows的DataRow博士){
            的foreach(对象我dr.ItemArray){
                输出+ = i.ToString()+\\ t的;
            }
            输出+ =\\ r \\ n;
        }
    }
}

}


解决方案

的几点,我注意到:


  

      
  1. 回调方法被调用后,才取出WAITFOR DELAY
      语句。

  2.   
  3. 无需轮询result.IsCompleted,因为
      回调方法仅被解雇后,
      异步处理完成。

  4.   
  5. 没有必要,因为默认情况下它明确设置=博士在其他部分空
      为null。

  6.   
  7. 您应该处理InvalidOperationException异常和
      ArgumentException的在
      HandleCallback方法。

  8.   
  9. 在手柄回调时,该EndExecuteReader()被调用我
      一直得到异常的
      异步操作早已
      完成。所以,我从来没有能够得到
      结果在博士。

  10.   

如果你正面临着​​点没有列出的问题。 5,可以使用通过异步委托,而不是内置的BeginExecuteReader()和EndExecuteReader()实施了以下替代的解决方案。在下面太液,控制会立即返回到下一行调用委托后,就像它发生在BeginExecuteReader()的情况下。

替代的解决方案:

 公共部分类窗体2:表
{
    公共窗体2()
    {
        的InitializeComponent();
    }    私人委托的DataSet GetDSDelegate(查询字符串);    私人无效的button1_Click(对象发件人,EventArgs的发送)
    {
        GetDSDelegate德尔=新GetDSDelegate(GetDataSetAsync);
        del.BeginInvoke(@前3 *从表1中选择;,NULL,NULL);
    }    私人数据集GetDataSetAsync(查询字符串)
    {
        数据集DS;
        使用(SqlConnection的康恩=新的SqlConnection(@数据源= mmmmm000011 \\ sqlex preSS;初始目录= SOExamples;集成安全性= SSPI;异步处理=真;))
        使用(CMD的SqlCommand =新的SqlCommand(查询,康涅狄格州))
        {
            尝试
            {
                conn.Open();
                SqlDataReader的博士= cmd.ExecuteReader();                DataTable的DT =新的DataTable();
                DS =新的DataSet();                dt.Load(DR);
                ds.Tables.Add(DT);
                dr.Close();
                完整(DS);
            }
            最后
            {
                如果(conn.State!= ConnectionState.Closed)
                    conn.Close();
            }
        }
        MessageBox.Show(完成!);
        返回DS;
    }    私人无效完成(DataSet的DS)
    {
        ...
    }
}

So, why doesn't this ever make it to the callback function?

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";
        }
    }
}

}

解决方案

Some points I noticed:

  1. The callback method was called only after I removed the WAITFOR DELAY stmt.
  2. There is no need to poll for result.IsCompleted, because the Callback method gets fired only after async processing is completed.
  3. No need to explicitly set dr = null in the else part because by default it will be null.
  4. You should handle InvalidOperationException and ArgumentException in the HandleCallback method.
  5. In the handle callback whenever, the EndExecuteReader() was called I kept getting the exception "The asynchronous operation has already completed." So I was never able to get the result in dr.

If you are facing the issue listed in point no. 5, you can use the following alternate solution implemented by using asynchronous delegates rather than the built-in BeginExecuteReader() and EndExecuteReader(). In the solution below too, the control will be immediately returned to the next line after the delegate is invoked, just like it happens in the case of BeginExecuteReader().

Alternate Solution:

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)
    {
        ...
    }
}

这篇关于SQL查询异步问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆