C# 实体框架Linq查询的问题:在SSMS中立即运行,在EF Linq中运行8-10秒

C# 实体框架Linq查询的问题:在SSMS中立即运行,在EF Linq中运行8-10秒,c#,sql,sql-server,linq,entity-framework,C#,Sql,Sql Server,Linq,Entity Framework,我在SQL(变量名模糊化)中得到了以下查询,该查询试图获取值(Ch、Wa、Bu、Hi),从而产生最大数量(cnt)的Pi条目 select top 1 Pi.Ch, Pi.Wa, Pi.Bu, Pi.Hi, COUNT(1) as cnt from Product, Si, Pi where Product.Id = Si.ProductId and Si.Id = Pi.SiId and Product.Code = @CodeParameter group by Pi.Ch, Pi.Wa,

我在SQL(变量名模糊化)中得到了以下查询,该查询试图获取值(Ch、Wa、Bu、Hi),从而产生最大数量(cnt)的Pi条目

select top 1 Pi.Ch, Pi.Wa, Pi.Bu, Pi.Hi, COUNT(1) as cnt 
from Product, Si, Pi
where Product.Id = Si.ProductId
and Si.Id = Pi.SiId
and Product.Code = @CodeParameter
group by Pi.Ch, Pi.Wa, Pi.Bu, Pi.Hi
order by cnt desc
它在SQL management studio中的生产数据库上立即运行。我已经在C#LINQ和实体框架中成功地编写了一些代码,但是每种方式的代码运行时间都在8-10秒。一次尝试是以下代码(在不打印的情况下执行,因为一次调用会产生相同的性能结果):

它输出以下SQL语句:

SELECT 
    [Project1].[C2] AS [C1], 
    [Project1].[Ch] AS [Ch], 
    [Project1].[Wa] AS [Wa], 
    [Project1].[Bu] AS [Bu], 
    [Project1].[Hi] AS [Hi], 
    [Project1].[C1] AS [C2]
    FROM ( SELECT 
        [GroupBy1].[A1] AS [C1], 
        [GroupBy1].[K1] AS [Ch], 
        [GroupBy1].[K2] AS [Wa], 
        [GroupBy1].[K3] AS [Bu], 
        [GroupBy1].[K4] AS [Hi], 
        1 AS [C2]
        FROM ( SELECT 
            [Extent3].[Ch] AS [K1], 
            [Extent3].[Wa] AS [K2], 
            [Extent3].[Bu] AS [K3], 
            [Extent3].[Hi] AS [K4], 
            COUNT(1) AS [A1]
            FROM   [dbo].[Product] AS [Extent1]
            INNER JOIN [dbo].[Si] AS [Extent2] ON [Extent1].[Id] = [Extent2].[ProductId]
            INNER JOIN [dbo].[Pi] AS [Extent3] ON [Extent2].[Id] = [Extent3].[SiId]
            WHERE ([Extent1].[Code] = @p__linq__0) AND (@p__linq__0 IS NOT NULL)
            GROUP BY [Extent3].[Ch], [Extent3].[Wa], [Extent3].[Bu], [Extent3].[Hi]
        )  AS [GroupBy1]
    )  AS [Project1]
    ORDER BY [Project1].[C1] DESC
我还尝试了查询语法,得到了大致相同的结果。我也尝试过直接使用EF进行查询(但时间不长),但无法很快让它工作

在将查询转换为LINQ时,我是否犯了一些错误?有没有一个明显的方法可以改进查询?是否可以使用与SQL语句相同的性能在EF/LINQ中编写查询

======更新======

在SQL分析器中,原始查询的输出完全相同。对于LINQ查询,它与我上面发布的内容非常相似

exec sp_executesql N'SELECT TOP (1) 
    [Project1].[C2] AS [C1], 
    [Project1].[Ch] AS [Ch], 
    [Project1].[Wa] AS [Wa], 
    [Project1].[Bu] AS [Bu], 
    [Project1].[Hi] AS [Hi], 
    [Project1].[C1] AS [C2]
    FROM ( SELECT 
        [GroupBy1].[A1] AS [C1], 
        [GroupBy1].[K1] AS [Ch], 
        [GroupBy1].[K2] AS [Wa], 
        [GroupBy1].[K3] AS [Bu], 
        [GroupBy1].[K4] AS [Hi], 
        1 AS [C2]
        FROM ( SELECT 
            [Extent3].[Ch] AS [K1], 
            [Extent3].[Wa] AS [K2], 
            [Extent3].[Bu] AS [K3], 
            [Extent3].[Hi] AS [K4], 
            COUNT(1) AS [A1]
            FROM   [dbo].[Product] AS [Extent1]
            INNER JOIN [dbo].[Si] AS [Extent2] ON [Extent1].[Id] = [Extent2].[ProductId]
            INNER JOIN [dbo].[Pi] AS [Extent3] ON [Extent2].[Id] = [Extent3].[SiId]
            WHERE ([Extent1].[Code] = @p__linq__0) AND (@p__linq__0 IS NOT NULL)
            GROUP BY [Extent3].[Ch], [Extent3].[Wa], [Extent3].[Bu], [Extent3].[Hi]
        )  AS [GroupBy1]
    )  AS [Project1]
    ORDER BY [Project1].[C1] DESC',N'@p__linq__0 nvarchar(4000)',@p__linq__0=N'109579'
======更新2======

下面是上的查询执行计划的模糊部分。注意,这里讨论的变量在输出中命名为“MagicalCode”,值“109579”和“2449-268-550”与XML输出的最后一行一样有效(C#中的字符串)

<ParameterList>
    <ColumnReference
        Column="@p__linq__0"
        ParameterCompiledValue="N'109579'"
        ParameterRuntimeValue="N'2449-268-550'" />
</ParameterList>

显示实际行数的平面图

======更新3======

(隐藏在注释中)我在SSMS中运行了从实体框架生成的EF SQL,它立即运行。因此,我可能正遭受着某种形式的参数嗅探,正如所暗示的。我不知道如何在实体框架的上下文中处理它

======更新4======

已更新,可使用打开

======更新5======

一些变通尝试

  • 使用
    context.Database.SqlQuery(…)
    运行原始查询大约需要4-5秒
  • 使用
    SqlCommand
    和从EF上下文获得的连接字符串运行原始查询大约需要3秒钟(上下文初始化开销)
  • 使用带有硬编码连接字符串的
    SqlCommand
    take运行原始查询大约需要1.5秒。 所以我现在用的是最后一个。我能想到的最后一件事是编写一个存储过程,以接近在SSMS中运行查询的“即时”性能

您可以尝试使用IQueryable.AsNoTracking()请参阅。在不打算编辑结果并再次将其保存回数据库的情况下,使用AsNoTracking()是安全的。通常,当查询返回大量行时,会产生很大的差异。如果要使用.AsNoTracking(),请确保将System.Data.Entity放入使用中。这可能是缓存执行计划的问题。尝试执行存储过程以清除查询执行计划:

DBCC FREEPROCCACHE

此外,此线程可能会有所帮助:

linq生成的查询没有
TOP1
?无论如何,请发布实际执行计划。@MartinSmith
query.ToString()
query.First()
之前执行,因此在使用EF(控制台应用程序、win应用程序、web应用程序)时,它不会显示
TOP 1
?生成的查询在SSMS中需要多长时间?请同时提供执行计划。
Product.code
的数据类型是什么?如果
varchar
您将被禁用,这将阻止对代码的搜索。我没有看到证据表明跟踪是问题的一部分。
DBCC FREEPROCCACHE