Доступ к сообщениям SQL Server через ADO.NET

Можно ли получить доступ к SQL Server "сообщения о побочных продуктах" через ADO.NET? Из-за отсутствия слов под "сообщениями о побочных продуктах" я подразумеваю вывод, который появляется на вкладке "Сообщения" в Microsoft SQL Server Management Studio. Что мне особенно важно, так это прочитать вывод SET STATISTICS TIME ON. Похоже, что SqlDataReader ничего не предлагает в этом вопросе.

3 ответа

Решение

Да, есть событие на SqlConnection класс называется SqlInfoMessage, в который вы можете зацепить:

SqlConnection _con = 
   new SqlConnection("server=.;database=Northwind;integrated Security=SSPI;");

_con.InfoMessage += new SqlInfoMessageEventHandler(InfoMessageHandler);

Обработчик события будет выглядеть так:

static void InfoMessageHandler(object sender, SqlInfoMessageEventArgs e)
{
    string myMsg = e.Message;            
}

e.Message это сообщение, распечатанное в окне сообщений в SQL Server Management Studio.

Спасибо за ответ выше. Я просто провел небольшой эксперимент и обнаружил небольшой неожиданный сбой (ошибка?) При чтении сообщений (в данном случае, созданных с помощью команды SET STATISTICS TIME ON) из результата с несколькими наборами записей. Как указано ниже, необходимо вызвать NextResult даже после последнего набора результатов, чтобы получить последнее сообщение. Это не требуется в случае результата с одним набором записей.

using System;
using System.Data.SqlClient;

namespace TimingTest
{
    class Program
    {

        static void Main(string[] args)
        {

            SqlConnection conn = new SqlConnection("some_conn_str");
            conn.Open();

            conn.InfoMessage += new SqlInfoMessageEventHandler(Message);

            SqlCommand cmd = new SqlCommand("some_sp", conn);
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            SqlDataReader rdr = cmd.ExecuteReader();

            while (rdr.Read()) { };

            rdr.NextResult();

            while (rdr.Read()) { };

            // this is needed to print the second message
            rdr.NextResult();

            rdr.Close();

            conn.Close();

        }

        static void Message(object sender, SqlInfoMessageEventArgs e)
        {
            Console.Out.WriteLine(e.Message);
        }

    }
}

Основываясь на ответе marc_s, я создал класс-оболочку

public class SqlInfoMessageWrapper
{
     public SqlInfoMessageWrapper(SqlConnection connection)
     {
            SqlConnection = connection;
            connection.InfoMessage += new SqlInfoMessageEventHandler(InfoMessageHandler);
      }
      public SqlConnection SqlConnection { get; set; }
      public string Message  { get; set; }

      void InfoMessageHandler(object sender, SqlInfoMessageEventArgs e)
      {
            Message = e.Message;
      }
 }

Пример использования:

    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        connection.Open();
        var messageWrapper=new SqlInfoMessageWrapper(connection) ;

        var ret = SqlHelper2.ExecuteNonQuery(connection, CommandType.Text, command, null);
        messages+= $"{messageWrapper.Message} number of rows affected {ret} ";
    }
Другие вопросы по тегам