Чем перехватить запросы от .NET приложения к MS SQL Server?
От: Министр Промышленности Россия  
Дата: 20.01.21 11:09
Оценка:
Чета то ли не приходилось это делать, то ли сделал и забыл...

Вот есть допустим Linq2Sql выражение, хочется увидеть какие SQL запросы оно отправит в базу данных.
Или есть запутанное большое приложение общающееся с базой, нужно увидеть все входящие запросы пришедшие к базе.

Напомните, как это делается?
Это — отъявленные охранители РосШвабНадзора, будьте бдительны!
Эдакий очередной путинский тухлячок...
Re: Чем перехватить запросы от .NET приложения к MS SQL Server?
От: Jericho113 Украина  
Дата: 20.01.21 11:15
Оценка: 25 (4) +1 -1
Здравствуйте, Министр Промышленности, Вы писали:

МП>Или есть запутанное большое приложение общающееся с базой, нужно увидеть все входящие запросы пришедшие к базе.


МП>Напомните, как это делается?


Раньше был SQL Server Profiler но он вроде бы уже deprecated и не развивается и рекомендуют использовать Extended Events для этого...
Но я по старинке все еще работаю SQL Server Profiler т.к. у меня 2012-2016 сиквел серваки
NetDigitally yours ....
Re[2]: Чем перехватить запросы от .NET приложения к MS SQL Server?
От: VladCore  
Дата: 21.01.21 06:30
Оценка: -1
Здравствуйте, Jericho113, Вы писали:

МП>>Или есть запутанное большое приложение общающееся с базой, нужно увидеть все входящие запросы пришедшие к базе.


МП>>Напомните, как это делается?


J>Раньше был SQL Server Profiler но он вроде бы уже deprecated и не развивается и рекомендуют использовать Extended Events для этого...


Это UI не развивается. А API развивается и ни разу не депрекатед:
https://docs.microsoft.com/en-us/sql/relational-databases/system-functions/sys-fn-trace-gettable-transact-sql?view=sql-server-ver15


J>Но я по старинке все еще работаю SQL Server Profiler т.к. у меня 2012-2016 сиквел серваки
Re[3]: Чем перехватить запросы от .NET приложения к MS SQL Server?
От: yenik  
Дата: 21.01.21 10:51
Оценка:
J>>Раньше был SQL Server Profiler но он вроде бы уже deprecated и не развивается и рекомендуют использовать Extended Events для этого...

VC>Это UI не развивается. А API развивается и ни разу не депрекатед:

VC>https://docs.microsoft.com/en-us/sql/relational-databases/system-functions/sys-fn-trace-gettable-transact-sql?view=sql-server-ver15

По ссылке.

Important

This feature will be removed in a future version of Microsoft SQL Server. Avoid using this feature in new development work, and plan to modify applications that currently use this feature. Use Extended Events instead.

Re[4]: Чем перехватить запросы от .NET приложения к MS SQL S
От: VladCore  
Дата: 21.01.21 12:22
Оценка:
Здравствуйте, yenik, Вы писали:

Y>По ссылке.

Y>

Y>Important

Y>This feature will be removed in a future version of Microsoft SQL Server. Avoid using this feature in new development work, and plan to modify applications that currently use this feature. Use Extended Events instead.


вот блин. ну и ладно. а мы по прежнему юзаем ::fn_trace_gettable вместо sys.fn_trace_gettable, она уже лет 12 депрекатед но работает в SQL 2019 хоть обычном хоть в линуксе

этоже sql сервер а не какой то там IE с macOS

кстати сиквела нового не будет, только Windows Server 2021 https://rcpmag.com/articles/2011/02/01/the-2011-microsoft-product-roadmap.aspx
Отредактировано 21.01.2021 12:27 VladCore . Предыдущая версия .
Re: Чем перехватить запросы от .NET приложения к MS SQL Server?
От: _FRED_ Россия
Дата: 28.01.21 10:06
Оценка: 3 (1) -1
Здравствуйте, Министр Промышленности, Вы писали:

МП>Чета то ли не приходилось это делать, то ли сделал и забыл...


МП>Вот есть допустим Linq2Sql выражение, хочется увидеть какие SQL запросы оно отправит в базу данных.


Неужели возникли какие-то проблемы с https://www.google.com/search?q=Linq2Sql+log+queries?

Вообще,
  1. Посмотреть, что для этого предлагает сам движок запросов. Например для EF Core Overview of Logging and Interception
  2. Если это не подходит, можно Enable event tracing in SqlClient, но тут сложнее — более низкоуровневая информация, зато для всего ADO.NET.

МП>Или есть запутанное большое приложение общающееся с базой, нужно увидеть все входящие запросы пришедшие к базе.


Опять же, если интересует то, что отправило приложение, то см. выше. Если то, что пришло на сервер, то уже средствами сервера. Для сиквела SQL Server Profiler или XEvent Profiler
Help will always be given at Hogwarts to those who ask for it.
Re: Чем перехватить запросы от .NET приложения к MS SQL Server?
От: Tom Россия http://www.RSDN.ru
Дата: 31.01.21 18:45
Оценка:
МП>Напомните, как это делается?


DiagnosticSource

Вот пример, потраха замени на свои:

using System;
using System.Text;
using System.Data.SqlClient;

using Microsoft.Extensions.DiagnosticAdapter;
using System.Diagnostics;
using System.Collections.Generic;
using Microsoft.SqlServer.Server;
using System.Linq;

namespace EDW.CrewPage.Telemetry.DiagnosticListeners
{
    public static class RequestTelemetryMiddlewareExtensions
    {
        public static IApplicationBuilder UseRequestTelemetry(
            this IApplicationBuilder app, 
            RequestTelemetryMiddlewareOptions options)
        {
            DiagnosticListener.AllListeners.Subscribe(new SqlClientListener());
        }
    }

    public class SqlClientListener : IObserver<DiagnosticListener>
    {
        private readonly List<IDisposable> _subscriptions;

        public SqlClientListener()
        {
            _subscriptions = new List<IDisposable>();
        }

        void IObserver<DiagnosticListener>.OnNext(DiagnosticListener diagnosticListener)
        {
            if (diagnosticListener.Name == "SqlClientDiagnosticListener")
            {
                var subscription = diagnosticListener.SubscribeWithAdapter(this);
                _subscriptions.Add(subscription);
            }
        }

        void IObserver<DiagnosticListener>.OnError(Exception error)
        { }

        void IObserver<DiagnosticListener>.OnCompleted()
        {
            _subscriptions.ForEach(x => x.Dispose());
            _subscriptions.Clear();
        }

        private string FormatSqlValue(object value)
        {
            switch (value)
            {
                case string s:
                    return $"'{value}'";

                case Guid g:
                    return $"'{value}'";

                case DateTime d:
                    return $"'{d:s}'";

                case bool b:
                    return b ? "1" : "0";

                case DBNull n:
                    return "NULL";

                default:
                    return value.ToString();
            }
        }

        [DiagnosticName("System.Data.SqlClient.WriteCommand")]
        public void IsEnabled1()
        {
            // FAKE event handler needed to make Start/Stop event handlers working
        }

        [DiagnosticName("System.Data.SqlClient")]
        public void IsEnabled2()
        {
            // FAKE event handler needed to make Start/Stop event handlers working
        }

        private string GenerateCommandParametersSql(SqlCommand sqlCommand)
        {
            var parameters = new SqlParameter[sqlCommand.Parameters.Count];
            sqlCommand.Parameters.CopyTo(parameters, 0);

            var sb = new StringBuilder();
            foreach (var sqlParameter in parameters)
            {
                if (sqlParameter.SqlDbType == System.Data.SqlDbType.Structured)
                {
                    var sqlType = sqlParameter.TypeName;
                    sb.Append($"DECLARE {sqlParameter.ParameterName} {sqlType}\r\n\r\n");
                    sb.Append($"INSERT INTO {sqlParameter.ParameterName} VALUES\r\n");
                    sb.Append(
                        string.Join(",\r\n", 
                        ((IEnumerable<SqlDataRecord>)sqlParameter.Value)
                            .Select(x => $"({FormatSqlValue(x.GetValue(0))})")));
                    sb.Append("\r\n");
                }
                else
                {
                    var sqlType = sqlParameter.SqlDbType + (sqlParameter.Size > 0 && sqlParameter.SqlDbType != System.Data.SqlDbType.TinyInt ? $"({sqlParameter.Size})" : "");
                    var sqlValue = FormatSqlValue(sqlParameter.Value);

                    sb.Append($"DECLARE {sqlParameter.ParameterName} {sqlType} = {sqlValue};\r\n");
                }

            }

            return sb.ToString();
        }

        private void OnCommandFinished(
            SqlCommand sqlCommand,
            Dictionary<object, object> statistics,
            Exception e)
        {
            if (sqlCommand == null)
            {
                return;
            }

            // Read time when command started
            var startTimeMs = TelemetryManager.GetTimelineItemTimeMark(sqlCommand);
            var endTimeMs = TelemetryManager.GetElapsedSinceOperationStarted();

            // Save time when command finished to use it later on possible reader dispose event
            TelemetryManager.SetTimelineItemTimeMark(sqlCommand);

            TelemetryManager.IncreaseSqlOperationsCounter();
            TelemetryManager.IncreaseSqlProcessingCounter(endTimeMs - startTimeMs);

            var exec = sqlCommand.CommandType == System.Data.CommandType.StoredProcedure ? "EXEC " : string.Empty;

            TelemetryManager.AddTimelineItem(
                new TimelineItem
                {
                    OperationName = exec + sqlCommand.CommandText,
                    OperationParameters = GenerateCommandParametersSql(sqlCommand),
                    StartTimeMs = startTimeMs,
                    EndTimeMs = endTimeMs,
                    IsException = e != null,
                    CssColor = e != null ? "red" : TelemetryConstants.SqlRequestCssColor
                });
        }

        [DiagnosticName("System.Data.SqlClient.WriteCommandBefore")]
        public void OnWriteCommandBefore(
            Guid operationId,
            string operation,
            Guid connectionId,
            SqlCommand command)
        {
            command.Connection.StatisticsEnabled = true;
            command.Connection.ResetStatistics();

            TelemetryManager.SetTimelineItemTimeMark(command);
        }

        [DiagnosticName("System.Data.SqlClient.WriteCommandAfter")]
        public void OnCommandExecuted(
            Guid operationId,
            string operation,
            Guid connectionId,
            SqlCommand command,
            Dictionary<object, object> statistics)
        {
            // TODO: OnCommandExecuted also could receive sql statistics so we could read it and aggregate/return per operation
            // TODO: Like number of rows read, number of bytes, etc...

            OnCommandFinished(command, statistics, null);
        }

        [DiagnosticName("System.Data.SqlClient.WriteCommandError")]
        public void OnCommandError(
            Guid operationId,
            string operation,
            Guid connectionId,
            SqlCommand command,
            Exception exception,
            Dictionary<object, object> statistics)
        {
            OnCommandFinished(command, statistics, exception);
        }
    }
}
Народная мудрось
всем все никому ничего(с).
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.