如何知道运行时哪个 Linq 语句生成了现有的 SQL?

Ton*_*ich 3 c# linq linq-to-entities entity-framework linq-to-sql

我希望以某种方式编写实体框架或 LINQ to SQL 查询,以便当我在 SQL Server Profiler 中看到 SQL 查询时,我可以快速识别哪个 LINQ 语句生成该 SQL,而无需进入调试器并跟踪它。该应用程序不会使用存储过程,这使得通过过程名称进行搜索变得容易。

有任何想法吗?有没有一种方法可以在 LINQ 查询中注入带有代码的静态字符串,仅用于识别查询而不影响查询结果?

更新
我添加此内容是为了响应日志记录建议。我不想在生产中一直运行日志记录,以防出现问题时需要查看某些 SQL。寻找一种性能成本最小的方法。向每个 linq 语句附加一些唯一的字符串,以便代码可以很容易地与 SQL 相关联?

Fab*_*ice 5

以下是可用于标记实体框架查询的扩展方法:

public static class ExtensionMethods
{
  public static IQueryable<T> SetQueryName<T>(this IQueryable<T> source,
    [CallerMemberName] String name = null,
    [CallerFilePath] String sourceFilePath = "",
    [CallerLineNumber] Int32 sourceLineNumber = 0)
  {
    var expr = Expression.NotEqual(Expression.Constant("Query name: " + name), Expression.Constant(null));
    var param = Expression.Parameter(typeof(T), "param");
    var criteria1 = Expression.Lambda<Func<T, Boolean>>(expr, param);

    expr = Expression.NotEqual(Expression.Constant($"Source: {sourceFilePath} ({sourceLineNumber})"), Expression.Constant(null));
    var criteria2 = Expression.Lambda<Func<T, Boolean>>(expr, param);

    return source.Where(criteria1).Where(criteria2);
  }
}
Run Code Online (Sandbox Code Playgroud)

以下是如何使用它:

context.Table1.SetQueryName().Where(x => x.C1 > 4)
Run Code Online (Sandbox Code Playgroud)

它将使用调用方法名称作为查询名称。

您可以指定另一个名称,如下所示:

context.Table1.SetQueryName("Search for numbers > 4").Where(x => x.Number > 4)
Run Code Online (Sandbox Code Playgroud)

SQL 如下所示:

SELECT 
    [Extent1].[Number] AS [Number]
    FROM (SELECT 
    [Table1].[Number] AS [Number]
    FROM [dbo].[Table1] AS [Table1]) AS [Extent1]
    WHERE
      (N'Query name: Search for numbers > 4' IS NOT NULL)
      AND
      (N'Source: C:\Code\Projects\MyApp\Program.cs (49)' IS NOT NULL)
      AND ([Extent1].[Number] > 4)
Run Code Online (Sandbox Code Playgroud)