0

我一直在看 Brent Ozar 的培训视频(对我来说是 SQL Guru),他谈到参数嗅探并说 EF 会这样做,但对于我来说,我无法获得一个有效的示例。我期待看到参数,但它只是用相等而不是@p1、@p2 创建这样的 SQL。

SELECT [p].[Id], [p].[Body], [p0].[Type]
FROM [Posts] AS [p]
INNER JOIN [PostTypes] AS [p0] ON [p].[PostTypeId] = [p0].[Id]
WHERE ([p].[PostTypeId] = 6) AND ([p].[CreationDate] >= '2011-01-01T00:00:00.000')

我通过搭建他的 StackOverflow2013 数据库创建了 DBContext,并在帖子类型上创建了一个外键以获取某种 JOIN。

有谁知道我如何获得使用 EF 进行参数嗅探的示例,因为这每次都会创建一个新的查询计划?

如果我调用存储过程,那么我可以获得参数嗅探。

我的 C# 代码如下

  var result = ctx.Posts
    .Include(x => x.PostType)
    .Where(x => x.PostTypeId == 6 && x.CreationDate >= new DateTime(2013, 01, 01))
        .Select(x => new {
           Id = x.Id,
           Body = x.Body, 
           Type = x.PostType.Type
         }).ToList();
4

1 回答 1

1

在我找到答案后不久:)

正如 Gert 在评论中所说,我必须传递一个变量,所以 EF 在那里做了一些魔术。因此,如果我将代码更改为此,则会发生:

var myId = 6;

var result = ctx.Posts
    .Include(x => x.PostType)
    .Where(x => x.PostTypeId == myId && x.CreationDate >= new DateTime(2013, 01, 01))
        .Select(x => new {
            Id = x.Id,
            Body = x.Body, 
            Type = x.PostType.Type
        }).ToList();

然后我得到这样的SQL

exec sp_executesql N'SELECT [p].[Id], [p].[Body], [p0].[Type]
FROM [Posts] AS [p]
INNER JOIN [PostTypes] AS [p0] ON [p].[PostTypeId] = [p0].[Id]
WHERE ([p].[PostTypeId] = @__myId_0) AND ([p].[CreationDate] >= ''2013-01-01T00:00:00.000'')',N'@__myId_0 int',@__myId_0=6

然后我可以执行另一个具有不同值的

exec sp_executesql N'SELECT [p].[Id], [p].[Body], [p0].[Type]
FROM [Posts] AS [p]
INNER JOIN [PostTypes] AS [p0] ON [p].[PostTypeId] = [p0].[Id]
WHERE ([p].[PostTypeId] = @__myId_0) AND ([p].[CreationDate] >= ''2013-01-01T00:00:00.000'')',N'@__myId_0 int',@__myId_0=7

然后我可以在执行计划中看到使用了相同的查询计划,因为第一个查询具有设置计划的第一个查询,然后第二个查询使用它并保留估计的 166 行但实际上只得到 4 行

在此处输入图像描述

如果我查看第二个查询属性,我也可以确认这一点,并且可以看到它是用 6 编译的 put 是用 7 运行的

在此处输入图像描述

于 2021-03-26T22:48:57.277 回答