簡體   English   中英

SqlCommand.ExecuteReaderAsync在存儲過程中的第一個SELECT語句之后停止觸發InfoMessage事件

[英]SqlCommand.ExecuteReaderAsync stops firing InfoMessage event after first SELECT statement in a stored procedure

我必須使用存儲過程來訪問數據,並使用從數據庫引擎發送的消息(如PRINT 'hello' )。

當我使用SQL連接的InfoMessage事件並將數據填充到DataTable ,一切都很完美。

但是,當我必須按順序讀取數據並使用SqlDataReader.ExecuteReaderAsync ,連接會在存儲過程中的第一個select語句之后停止觸發InfoMessage:

C#代碼:

using (SqlConnection con = new SqlConnection("connection-string"))
{
    con.Open();
    con.InfoMessage += (s, e) => {
        Console.WriteLine(e.Message);
    };

    using (SqlCommand command = new SqlCommand("spTestMessage", con))
    {
        command.CommandType = System.Data.CommandType.StoredProcedure;

        SqlDataReader reader = await command.ExecuteReaderAsync();

        int cntr = 0;

        while (reader.Read())
        {
            Console.WriteLine($"Loaded row {cntr++}");
        }

        // reader.NextResult(); // this line forces firing rest of InfoMessage events
    }
}

SQL存儲過程:

CREATE PROCEDURE [dbo].[spTestMessage]
AS

PRINT 'Before select 1'
select * from MyTable
PRINT 'After select 1'

PRINT 'Before select 2'
select * from MyTable
PRINT 'After select 2'

節目輸出:

Before select 1

為什么它停止工作? 我認為Reader有問題,因為當我使用command.ExecuteNonQueryAsync(); 而不是command.ExecuteReaderAsync(); ,它也有效。

我偶然發現,那個評論的行reader.NextResult(); 強制連接刷新消息並觸發剩余事件。 然而,這是一個非常不吉利的解決方法。

謝謝你的幫助!

你的command.ExecuteNonQueryAsync()在第一次運行后停止給出你的結果,有或沒有reader.ReadAsync() ,因為任何async SQL命令將在第一個結果返回給客戶端時完成,並且info messages算得上了。 當你觸發reader.NextResult() or await reader.NextResultAsync()它會與讀者聯系以獲得更多結果。

如果您想了解有關Asynchronous SQL處理的更多信息,可以查看Remus的答案,對於NextResult請查看此示例

使用InfoMessages

var _msgs = new List<string>();
using (System.Data.SqlClient.SqlConnection con = new System.Data.SqlClient.SqlConnection(<YourConnectionString>))
{
    //Appending an event handler for InfoMessages
    con.InfoMessage += delegate (object sender, SqlInfoMessageEventArgs args)
    {
        //reader will invoke the delegate on every itteration of results coming from query
        _msgs.Add(args.Message);
        return;
    };
    using (var cmd = new System.Data.SqlClient.SqlCommand("spTestMessage", con))
    {
        cmd.CommandType = CommandType.StoredProcedure;
        con.Open();
        using (System.Data.SqlClient.SqlDataReader reader = await cmd.ExecuteReaderAsync())
        {
            var incr = 0;
            while (await reader.ReadAsync())
            {
                //Statements to read data from Table1
                Console.WriteLine(reader.GetString(0));
                incr++;
            }
            while (await reader.NextResultAsync())
            {
                while (await reader.ReadAsync())
                {
                     //Statements to read data from Table2
                     Console.WriteLine(reader.GetString(0));
                     incr++;
                 }
             }
         }
     } 
}

注意:上述過程可以與Synchronous操作一起使用,只需將方法的簽名從異步更改為同步即可。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM