在每个类型的表继承中计算查询生成

时间:2016-11-03 15:57:25

标签: c# asp.net-mvc entity-framework table-per-type

我有一个典型的TPT场景(不要问我为什么要做TPT,这可能是一个愚蠢的选择),我试图在BASE类型上运行一个简单的Count查询。 鉴于计数是基于基类型和基类的属性,我无法理解为什么,但EF通过将所有派生类型连接在一起来创建COUNT(*)查询。

这些类是这样的:

public abstract class StudyCase {
    public DateTime? DateSubmitted { get; protected set; }
    public bool Deleted { get; set; }
}

public class StudyCaseStandard : StudyCase { 
// ... other stuff
}

public class StudyCaseReview : StudyCase { 
// ... other stuff
}

我的查询是这样的

SubmittedCasesCount = _context.Set<StudyCase>().Where(sc => !sc.Deleted).Count(sc => sc.DateSubmitted.HasValue);

这是由EF生成的查询(上面没有显示第三个类但在查询中看到):

SELECT 
    [GroupBy1].[A1] AS [C1]
    FROM ( SELECT 
        COUNT(1) AS [A1]
        FROM   (SELECT 
            [Extent1].[Id] AS [Id]
            FROM [dbo].[StudyCases_Exacerbation] AS [Extent1]
        UNION ALL
            SELECT 
            [Extent2].[Id] AS [Id]
            FROM [dbo].[StudyCases_Standard] AS [Extent2]
        UNION ALL
            SELECT 
            [Extent3].[Id] AS [Id]
            FROM [dbo].[StudyCases_Review] AS [Extent3]) AS [UnionAll2]
        INNER JOIN [dbo].[StudyCases] AS [Extent4] ON [UnionAll2].[Id] = [Extent4].[Id]
        WHERE ([Extent4].[Deleted] <> 1) AND ([Extent4].[DateSubmitted] IS NOT NULL)
    )  AS [GroupBy1]
go

正如您所看到的那样,UNIONJOIN正在完成所有SELECT COUNT(1) AS [A1] FROM [dbo].[StudyCases] WHERE ([Deleted] <> 1) AND ([DateSubmitted] IS NOT NULL) abstract,而这样做一个简单的计数会更有效(也是唯一必要的):

FIND /?

任何想法如何在不需要派生类的属性时或者当返回集只是基类的集合时强制EF生成更简单的查询(这可能取决于FIND上的FIND [/V] [/C] [/N] [/I] [/OFF[LINE]] "string" [[drive:][path]filename[ ...]] /V Displays all lines NOT containing the specified string. /C Displays only the count of lines containing the string. /N Displays line numbers with the displayed lines. /I Ignores the case of characters when searching for the string. /OFF[LINE] Do not skip files with offline attribute set. "string" Specifies the text string to find. [drive:][path]filename Specifies a file or files to search. If a path is not specified, FIND searches the text typed at the prompt or piped from another command. 关键字基类,但EF应该能够实现抽象类的代理?)

1 个答案:

答案 0 :(得分:2)

如果使用select语句仅从基类中提取属性,则生成什么查询,如下所示:

SubmittedCasesCount = 
    _context
        .Set<StudyCase>()
        .Select(sc => new { Deleted = sc.Deleted, DateSubmitted = sc.DateSubmitted })
        .Where(anon => !anon.Deleted)
        .Count(anon => anon.DateSubmitted.HasValue);

编辑: 遗憾的是,上面生成相同的查询,我所知道的唯一其他解决方案是执行原始SQL查询,如:

int count = context.Set<StudyCase>
                   .FromSql("SELECT Deleted, DateSubmitted FROM dbo.StudyCases")
                   .Where(sc => !sc.Deleted).Count(sc => sc.DateSubmitted.HasValue)
                   .Count();