Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

Да, есть событие в классе 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.

Ответ 2

Спасибо за ответ выше. Я просто немного экспериментировал и обнаружил неожиданный сбой (ошибка?) При чтении сообщений (в этом случае, произведенных 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);
        }

    }
}

Ответ 3

Основываясь на ответе 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} ";
    }