2

Мы используем newrelic для мониторинга производительности базы данных. Наши проблемы - это структура Entity, генерирующая SQL, и у нас возникают проблемы с отслеживанием, где этот SQL-запрос был сгенерирован в нашей базе кода, напримерEntity framework добавление Пользовательский метод

Допустим, что приведенный ниже запрос вызывает проблемы с производительностью. Как я могу изменить сгенерированный SQL запрос и добавить свой комментарий на нем, например

SELECT 
    ? AS [C1], 
    [GroupBy1].[K1] AS [Destination], 
    [GroupBy1].[A1] AS [C2] 
    FROM (SELECT 
     [Extent1].[Destination] AS [K1], 
     SUM([Extent1].[SearchCount]) AS [A1] 
     FROM [Flight].[Item] AS [Extent1] 
     WHERE ([Extent1].[Origin] IN (?, ?)) AND (NOT ((@p__linq__0 = ?) AND ([Extent1].[IsDomesticTurkish] = ?))) AND ([Extent1].[DestinationCity] IN (?, ?, ?, ?, ?, ?, ?, ?)) AND ([Extent1].[DestinationCity] IS NOT NULL) 
     GROUP BY [Extent1...More… 

Так как я могу сделать что-то вроде этого вар DbContext.MyDbSet.Where (myWhereEx) .AddCustomComment ("Привет, это обычай комментарии я буду писать от моего кода ")

После этого выход будет как этот

SELECT 
    ? AS [C1], 
    [GroupBy1].[K1] AS [Destination], 
    [GroupBy1].[A1] AS [C2] 
    FROM (SELECT 
     [Extent1].[Destination] AS [K1], 
     SUM([Extent1].[SearchCount]) AS [A1] 
     FROM [Flight].[Item] AS [Extent1] 
     WHERE ([Extent1].[Origin] IN (?, ?)) AND (NOT ((@p__linq__0 = ?) AND ([Extent1].[IsDomesticTurkish] = ?))) AND ([Extent1].[DestinationCity] IN (?, ?, ?, ?, ?, ?, ?, ?)) AND ([Extent1].[DestinationCity] IS NOT NULL) 
     GROUP BY [Extent1...More… 

--Hello this is a custom comment I will write it from my code 

Мой вопрос состоит в том, как реализовать AddCustomComment и внутри AddCustomComment изменить сгенерированный SQL, прежде чем он идет к SQL серверу

ответ

1

Я не знаю о каких-либо встроенных функциях EF для этого, но вот одна идея, как это можно сделать.

Вы можете использовать локальную переменную потока для хранения комментариев (так что каждый поток имеет собственную копию этой переменной) и использовать перехватчик команд Entity Framework, чтобы добавить комментарий к команде перед ее исполнением, а затем очистить переменную комментария, когда команда была казнены. Вот пример реализации:

class EFCommentInterceptor : IDbCommandInterceptor { 
    private static readonly ThreadLocal<string> _comment = new ThreadLocal<string>(); 

    internal static void SetComment(string comment) { 
     _comment.Value = comment; 
    } 

    public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext) { 
     AddComment(command); 
    } 

    public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext) { 
     _comment.Value = null; 
    } 

    public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext) { 
     AddComment(command); 
    } 

    public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext) { 
     _comment.Value = null; 
    } 

    public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext) { 
     AddComment(command); 
    } 

    public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext) { 
     _comment.Value = null; 
    } 

    private void AddComment(DbCommand command) { 
     if (!String.IsNullOrWhiteSpace(_comment.Value)) 
      command.CommandText += "\r\n\r\n-- " + _comment.Value; 
    } 
} 

Затем добавить метод расширения, как это:

static class QueryableExtensions { 
    public static IQueryable<T> WithComment<T>(this IQueryable<T> query, string comment) { 
     EFCommentInterceptor.SetComment(comment); 
     return query; 
    } 
} 

Регистрация перехватчик:

DbInterception.Add(new EFCommentInterceptor()); 

И использовать его:

using (var ctx = new MyContext()) { 
    ctx.MyDbSet.Where(c = c.MyColumn > 1).WithComment("Hello this is a custom comment I will write it from my code").ToArray(); 
    ctx.MyDbSet.Take(10).ToArray(); // no comment here 
    ctx.MyDbSet.Take(10).WithComment("Again with comment").ToArray(); 
} 
+0

Благодарим Вас за help – mhdbaz

+0

Любая помощь ab получить решение выше в Entity Framework Core? – mhdbaz

+0

К сожалению, я мало знаю о ядре EF, потому что на данный момент он находится в слишком сыром состоянии и у меня не хватает многих функций. Например, ему все еще не хватает DbInterceptor, поэтому вы не можете реализовать это точное решение, как есть. Однако, возможно, это позволяет предоставить некоторые другие крючки, о которых я не знаю. – Evk