编程语言
首页 > 编程语言> > c# – BeginExecuteReader,EndExecuteReader和多个结果

c# – BeginExecuteReader,EndExecuteReader和多个结果

作者:互联网

我有从我的数据库异步获取结果的方法:

internal class CommandAndCallback<TCallback, TError>
{
    public SqlCommand Sql { get; set; }
    public TCallback Callback { get; set; }
    public TError Error { get; set; }
}

public void GetResults(string param, Action<DataTable,DataTable> callback, Action<string> error, Action<string> info)
{
    var conn = new SqlConnection(_connString);
    conn.InfoMessage += delegate(object sender, SqlInfoMessageEventArgs e)
    {
        if (e.Errors.Count <= 0) return;
        foreach (SqlError message in e.Errors)
        {
            info(message.State + " " + message.Message);
        }
    };
    SqlCommand cmd = conn.CreateCommand();
    cmd.CommandTimeout = 0;
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.CommandText = @"GetData";
    cmd.Parameters.Add("@param", SqlDbType.NVarChar).Value = param;

    try
    {
        cmd.Connection.Open();
    }
    catch (Exception ex)
    {
        error(ex.ToString());
        return;
    }

    var ar = new CommandAndCallback<Action<DataTable,DataTable>, Action<string>> { Callback = callback, Error = error, Sql = cmd };
    cmd.BeginExecuteReader(Krok2_Handler, ar, CommandBehavior.CloseConnection);
}

private static void Krok2_Handler(IAsyncResult result)
{
    var ar = (CommandAndCallback<Action<DataTable,DataTable>, Action<string>>)result.AsyncState;

    if (result.IsCompleted)
    {
        try
        {
            SqlDataReader dr = ar.Sql.EndExecuteReader(result);
            var dt1 = new DataTable();
            var dt2 = new DataTable();
            dt1.Load(dr);
            if (dr.NextResult())//I can't access second table in results
            {
                dt2.Load(dr);
            }
            dr.Close();
            ar.Callback(dt1,dt2);
        }
        catch (Exception ex)
        {
            ar.Error(ex.Message);
        }
    }
    else
    {
        ar.Error("Error calling SQL");
    }
}

我称之为:

GetResults("Param value, Success, Error, Info);

当我的程序返回单个结果时,一切正常,但是当我添加第二个选择时,我的数据读取器没有得到它们,可能是因为当我调用EndExecuteReader连接时正在关闭.

如何修改我的代码以支持多个结果,以便将它们传递给我的回调方法?

解决方法:

我测试了这个,我认为问题出在这里:

dt1.Load(dr);
if (dr.NextResult())//I can't access second table in results
{
  dt2.Load(dr);
}

从我可以看到,对Load的调用会自动将SqlDataReader推进到下一个记录集,因此对dr.NextResult()的调用将返回false.

如果你这样做,我认为你会发现它有效,它对我有用:

dt1.Load(dr);
dt2.Load(dr);

编辑:
 我刚检查了DataTable.Load的源代码,它确实为您调用了NextResult方法:

if (!reader.IsClosed && !reader.NextResult())
{
    reader.Close();
}

EDIT2
在循环SqlDataReader时,你应该使用这个:

if (result.IsCompleted)
{
    try
    {
        List<string> table1 = new List<string>();
        List<string> table2 = new List<string>();
        SqlDataReader dr = ar.Sql.EndExecuteReader(result);

        while (dr.Read())
        {
            table1.Add(dr[0].ToString());//get data from first table
        }

        if (dr.NextResult())//second table
        {
            while (dr.Read())
            {
                table2.Add(dr[0].ToString()); //get data from second table
            }
        }

        dr.Close();
        ar.Callback(table1 ,table2);
    }
    catch (Exception ex)
    {
        ar.Error(ex.Message);
    }
}

标签:c,asynchronous,net,net-4-5,sqldatareader
来源: https://codeday.me/bug/20190624/1275706.html