Entity Framework C# 中的 EDMX 使用@p__linq__0 隐藏参数值

Entity Framework EDMX in C# hiding parameter values with @p__linq__0

我继承了一些项目,其中 VS 应用程序显然使用旧的 EDMX。我不记得过去有过如此困难的查询,尤其是在计算参数时..

当我逐步执行代码时,我看到了各种 IQueryable<T> 语句,例如

IQueryable<BreakDomainModel> breakDomainModels = breakFactoryService.ReadBreakData();

大家好像都隐藏的太深了,排查起来很困难。

部分例子SQL

CASE WHEN ([Extent2].[BreakId] IS NOT NULL) THEN [Extent3].[Name] ELSE @p__linq__0 END AS [C6], 
CASE WHEN ([Extent2].[BreakId] IS NOT NULL) THEN  CAST( [Extent2].[DateCreated] AS datetime2) END AS [C7], 
[Extent1].[ExceptionType] AS [ExceptionType], 
[Extent1].[LinkId] AS [LinkId], 
CASE WHEN ([Extent2].[BreakId] IS NOT NULL) THEN [Extent2].[Age] ELSE @p__linq__1 END AS [C8]

如何单步执行代码并实际获取 @p__linq__0 等的值?

如果需要,我可以提供更多代码,但简单的 F11 和使用手表是无济于事的。

运行 SQL 探查器会话可能最容易查看生成的查询。

请参阅此答案以获得更好的解决方案: View Generated Sql

您可以注册自己的 DbCommandInterceptor. Take a look at this 关于 EF 日志记录的文章。请注意,为了记录参数,您必须迭代 DbCommand.Parameters。记录 Select 查询的最小解决方案是:

public class LoggingCommandInterceptor : DbCommandInterceptor
{
    public override void ReaderExecuting(DbCommand command,
        DbCommandInterceptionContext<DbDataReader> interceptionContext)
    {
        var parameters = command.Parameters.Cast<DbParameter>()
            .Select(x => $"{x.ParameterName}:{x.Value}");
        // It's up to you how you initialize the logger
        GetLogger().Debug($"Parameters: {string.Join(", ", parameters)}\r\n Query: {command.CommandText}");

        base.ReaderExecuting(command, interceptionContext);
    }
}

然后您需要做的就是在您的应用程序启动代码中注册该拦截器 (global.asax/Startup.cs/etc):

DbInterception.Add(new LoggingCommandInterceptor());

如果您只关心在调试时获取参数,只需在方法内放置一个断点,每次 EF 访问数据库时都会命中。

请注意,您必须以相同的方式覆盖其他方法(NonQueryExecuting()ScalarExecuting()),以便也拦截 update/instert/delete 查询。