实体框架超时但是从分析器查询在毫秒内执行

时间:2016-09-12 09:30:52

标签: c# entity-framework

以下代码在60秒后超时。它应该返回10K行以用于只读目的:

using (var db = new TUdvEntities(_connectionString))
{
    try
    {
        db.Set<TEjendom>().AsNoTracking();
        db.Set<TEjd_ESR>().AsNoTracking();
        db.Set<TMat>().AsNoTracking();

        IQueryable<TEjendom> query = db.TEjendom;

        foreach (var propertyId in propertiesInProgress)
        {
            query = query.Where(x => x.EjdId != propertyId);
        }

        var description = propertyState.GetDescription();

        var resultListTmp = query.Where(x => x.EjdStatus == description)
            .Include(nameof(TEjd_ESR))
            .Include(nameof(TMat))
            .Take(amount).ToList();
    ....
    }
}

但是,EF生成的查询(我从SQL Server Profiler中获取的)在一毫秒内执行。

我尝试使用以下命令禁用更改跟踪:

db.Configuration.AutoDetectChangesEnabled = false;

但这并没有帮助。

两个包含的组合会减慢查询速度,但是当我删除其中一个时,它会返回即时结果。

SQL查询:

exec sp_executesql N'SELECT 
    [UnionAll1].[EjdId] AS [C1], 
    [UnionAll1].[EjdId1] AS [C2], 
    [UnionAll1].[EjdType] AS [C3], 
    [UnionAll1].[BNummer] AS [C4], 
    [UnionAll1].[TNummer] AS [C5], 
    [UnionAll1].[ANummer] AS [C6], 
    [UnionAll1].[ENummer] AS [C7], 
    [UnionAll1].[Beskrivelse] AS [C8], 
    [UnionAll1].[SBT] AS [C9], 
    [UnionAll1].[EjdStatus] AS [C10], 
    [UnionAll1].[StatusTimestamp] AS [C11], 
    [UnionAll1].[IAbo] AS [C12], 
    [UnionAll1].[AOAttempts] AS [C13], 
    [UnionAll1].[AboId] AS [C14], 
    [UnionAll1].[BFE] AS [C15], 
    [UnionAll1].[UpdateToken] AS [C16], 
    [UnionAll1].[FEJ] AS [C17], 
    [UnionAll1].[C1] AS [C18], 
    [UnionAll1].[ESRId] AS [C19], 
    [UnionAll1].[EjdId2] AS [C20], 
    [UnionAll1].[Passiv] AS [C21], 
    [UnionAll1].[EjdId3] AS [C22], 
    [UnionAll1].[C2] AS [C23], 
    [UnionAll1].[C3] AS [C24], 
    [UnionAll1].[C4] AS [C25], 
    [UnionAll1].[C5] AS [C26]
    FROM  (SELECT 
        CASE WHEN ([Extent2].[ESRId] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1], 
        [Limit1].[EjdId] AS [EjdId], 
        [Limit1].[EjdId] AS [EjdId1], 
        [Limit1].[EjdType] AS [EjdType], 
        [Limit1].[BNummer] AS [BNummer], 
        [Limit1].[TNummer] AS [TNummer], 
        [Limit1].[ANummer] AS [ANummer], 
        [Limit1].[ENummer] AS [ENummer], 
        [Limit1].[Beskrivelse] AS [Beskrivelse], 
        [Limit1].[SBT] AS [SBT], 
        [Limit1].[EjdStatus] AS [EjdStatus], 
        [Limit1].[StatusTimestamp] AS [StatusTimestamp], 
        [Limit1].[IAbo] AS [IAbo], 
        [Limit1].[AOAttempts] AS [AOAttempts], 
        [Limit1].[AboId] AS [AboId], 
        [Limit1].[BFE] AS [BFE], 
        [Limit1].[UpdateToken] AS [UpdateToken], 
        [Limit1].[FEJ] AS [FEJ], 
        [Extent2].[ESRId] AS [ESRId], 
        [Extent2].[EjdId] AS [EjdId2], 
        [Extent2].[Passiv] AS [Passiv], 
        [Extent2].[EjdId] AS [EjdId3], 
        CAST(NULL AS int) AS [C2], 
        CAST(NULL AS varchar(1)) AS [C3], 
        CAST(NULL AS varchar(1)) AS [C4], 
        CAST(NULL AS int) AS [C5]
        FROM   (SELECT TOP (10416) 
            [Extent1].[EjdId] AS [EjdId], 
            [Extent1].[EjdType] AS [EjdType], 
            [Extent1].[BNummer] AS [BNummer], 
            [Extent1].[TNummer] AS [TNummer], 
            [Extent1].[ANummer] AS [ANummer], 
            [Extent1].[ENummer] AS [ENummer], 
            [Extent1].[Beskrivelse] AS [Beskrivelse], 
            [Extent1].[SBT] AS [SBT], 
            [Extent1].[EjdStatus] AS [EjdStatus], 
            [Extent1].[StatusTimestamp] AS [StatusTimestamp], 
            [Extent1].[IAbo] AS [IAbo], 
            [Extent1].[AOAttempts] AS [AOAttempts], 
            [Extent1].[AboId] AS [AboId], 
            [Extent1].[BFE] AS [BFE], 
            [Extent1].[UpdateToken] AS [UpdateToken], 
            [Extent1].[FEJ] AS [FEJ]
            FROM [dbo].[TEjendom] AS [Extent1]
            WHERE ([Extent1].[EjdStatus] = @p__linq__0) OR (([Extent1].[EjdStatus] IS NULL) AND (@p__linq__0 IS NULL)) ) AS [Limit1]
        LEFT OUTER JOIN [dbo].[TEjd_ESR] AS [Extent2] ON [Limit1].[EjdId] = [Extent2].[EjdId]
    UNION ALL
        SELECT 
        2 AS [C1], 
        [Limit2].[EjdId] AS [EjdId], 
        [Limit2].[EjdId] AS [EjdId1], 
        [Limit2].[EjdType] AS [EjdType], 
        [Limit2].[BNummer] AS [BNummer], 
        [Limit2].[TNummer] AS [TNummer], 
        [Limit2].[ANummer] AS [ANummer], 
        [Limit2].[ENummer] AS [ENummer], 
        [Limit2].[Beskrivelse] AS [Beskrivelse], 
        [Limit2].[SBT] AS [SBT], 
        [Limit2].[EjdStatus] AS [EjdStatus], 
        [Limit2].[StatusTimestamp] AS [StatusTimestamp], 
        [Limit2].[IAbo] AS [IAbo], 
        [Limit2].[AOAttempts] AS [AOAttempts], 
        [Limit2].[AboId] AS [AboId], 
        [Limit2].[BFE] AS [BFE], 
        [Limit2].[UpdateToken] AS [UpdateToken], 
        [Limit2].[FEJ] AS [FEJ], 
        CAST(NULL AS int) AS [C2], 
        CAST(NULL AS int) AS [C3], 
        CAST(NULL AS bit) AS [C4], 
        CAST(NULL AS int) AS [C5], 
        [Extent4].[EjdId] AS [EjdId2], 
        [Extent4].[LeKode] AS [LeKode], 
        [Extent4].[MatNummer] AS [MatNummer], 
        [Extent4].[EjdId] AS [EjdId3]
        FROM   (SELECT TOP (10416) 
            [Extent3].[EjdId] AS [EjdId], 
            [Extent3].[EjdType] AS [EjdType], 
            [Extent3].[BNummer] AS [BNummer], 
            [Extent3].[TNummer] AS [TNummer], 
            [Extent3].[ANummer] AS [ANummer], 
            [Extent3].[ENummer] AS [ENummer], 
            [Extent3].[Beskrivelse] AS [Beskrivelse], 
            [Extent3].[SBT] AS [SBT], 
            [Extent3].[EjdStatus] AS [EjdStatus], 
            [Extent3].[StatusTimestamp] AS [StatusTimestamp], 
            [Extent3].[IAbo] AS [IAbo], 
            [Extent3].[AOAttempts] AS [AOAttempts], 
            [Extent3].[AboId] AS [AboId], 
            [Extent3].[BFE] AS [BFE], 
            [Extent3].[UpdateToken] AS [UpdateToken], 
            [Extent3].[FEJ] AS [FEJ]
            FROM [dbo].[TEjendom] AS [Extent3]
            WHERE ([Extent3].[EjdStatus] = @p__linq__0) OR (([Extent3].[EjdStatus] IS NULL) AND (@p__linq__0 IS NULL)) ) AS [Limit2]
        INNER JOIN [dbo].[TMat] AS [Extent4] ON [Limit2].[EjdId] = [Extent4].[EjdId]) AS [UnionAll1]
    ORDER BY [UnionAll1].[EjdId1] ASC, [UnionAll1].[C1] ASC',N'@p__linq__0 nvarchar(4000)',@p__linq__0=N'HentData'

有什么建议吗?

1 个答案:

答案 0 :(得分:0)

我同意Allan S. Hansen关于参数嗅探的评论。

您的查询部分包含WHERE ([Extent1].[EjdStatus] = @p__linq__0)@p__linq__0参数在结尾的查询中以nvarchar(4000)传递:

ORDER BY [UnionAll1]。[EjdId1] ASC,[UnionAll1]。[C1] ASC',N'@ p__linq__0 nvarchar(4000)',@ p__linq__0 = N'HentData'

我猜测EjdStatus列未在数据库中定义为nvarchar(4000)。我相信这会使数据库选择错误的执行计划或索引。我们遇到了这个问题,我们所做的是确保EF查询使用了正确的数据类型并且帮助了很多。

我们通过在数据上下文中调用HasDataType覆盖中的OnModelCreating方法来完成此操作:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<MyClass>().Property(a => a.EjdStatus).HasColumnType("VARCHAR");

    //other code here
}

这导致EF在它生成的查询中使用正确的数据类型,这允许Sql选择适当的执行计划。