LINQ生成的SQL查询包含两个相同的SELECT

时间:2015-12-27 18:35:25

标签: sql entity-framework linq-to-sql

我有这个简单的LINQ,我无法弄清楚为什么结果SQL如此奇怪。

这是LINQ:

var query =
(
    from fileRecord in _context.FileRecords
    join linkAttr in _context.LinkAttributes on fileRecord.Id equals linkAttr.FileRecordId
    where linkAttr.ValidTo == null
    join titleAttr in _context.TitleAttributes on fileRecord.Id equals titleAttr.FileRecordId into titleGJ
    join textAttr in _context.TextAttributes on fileRecord.Id equals textAttr.FileRecordId into textGJ
    join publishedAttr in _context.PublishedAttributes on fileRecord.Id equals publishedAttr.FileRecordId into publishedGJ
    select new Set
    {
        Id = fileRecord.Id,
        ParentId = fileRecord.Type == FileRecordType.Photobank ? null : linkAttr.ParentId,
        Title =
        (
            from titleAttr in titleGJ
            where titleAttr.ValidTo == null && titleAttr.CultureId == cultureId
            select titleAttr.Title
        ).FirstOrDefault(),
        Text =
        (
            from textAttr in textGJ
            where textAttr.ValidTo == null && textAttr.CultureId == cultureId
            select textAttr.Text
        ).FirstOrDefault(),
        Published =
        (
            from publishedAttr in publishedGJ
            where publishedAttr.ValidTo == null && publishedAttr.CultureId == cultureId
            select publishedAttr.Published
        ).FirstOrDefault()
    }
);

所有三个实体 - 在这种情况下,TitleAttribute,TextAttribute和PublishedAttribute几乎是相同的类,PublishedAttribute包含一个以上的属性,但在LINQ中没有使用。

但生成的查询很奇怪。从PublishedAttributes表中选择有两次(由注释标记):

SELECT 
    [Project12].[Id] AS [Id], 
    CASE WHEN (5 = [Project12].[Type]) THEN CAST(NULL AS int) ELSE [Project12].[ParentId] END AS [C1], 
    [Project12].[C1] AS [C2], 
    [Project12].[C2] AS [C3], 
    CASE WHEN ([Project12].[C3] IS NULL) THEN cast(0 as bit) ELSE [Project12].[C4] END AS [C4]
    FROM ( SELECT 
        [Project10].[Id] AS [Id], 
        [Project10].[Type] AS [Type], 
        [Project10].[ParentId] AS [ParentId], 
        [Project10].[C1] AS [C1], 
        [Project10].[C2] AS [C2], 
        [Project10].[C3] AS [C3], 
        -- THIS ONE
        (SELECT TOP (1) 
            [Extent6].[Published] AS [Published]
            FROM [fs].[PublishedAttributes] AS [Extent6]
            WHERE ([Project10].[Id] = [Extent6].[FileRecordId]) AND ([Extent6].[ValidTo] IS NULL) AND ([Extent6].[CultureId] = @p__linq__3)) AS [C4]
        FROM ( SELECT 
            [Project9].[Id] AS [Id], 
            [Project9].[Type] AS [Type], 
            [Project9].[ParentId] AS [ParentId], 
            [Project9].[C1] AS [C1], 
            [Project9].[C2] AS [C2], 
            [Project9].[C3] AS [C3]
            FROM ( SELECT 
                [Project7].[Id] AS [Id], 
                [Project7].[Type] AS [Type], 
                [Project7].[ParentId] AS [ParentId], 
                [Project7].[C1] AS [C1], 
                [Project7].[C2] AS [C2], 
                -- AND THIS ONE
                (SELECT TOP (1) 
                    [Extent5].[Published] AS [Published]
                    FROM [fs].[PublishedAttributes] AS [Extent5]
                    WHERE ([Project7].[Id] = [Extent5].[FileRecordId]) AND ([Extent5].[ValidTo] IS NULL) AND ([Extent5].[CultureId] = @p__linq__3)) AS [C3]
                FROM ( SELECT 
                    [Project6].[Id] AS [Id], 
                    [Project6].[Type] AS [Type], 
                    [Project6].[ParentId] AS [ParentId], 
                    [Project6].[C1] AS [C1], 
                    [Project6].[C2] AS [C2]
                    FROM ( SELECT 
                        [Project4].[Id] AS [Id], 
                        [Project4].[Type] AS [Type], 
                        [Project4].[ParentId] AS [ParentId], 
                        [Project4].[C1] AS [C1], 
                        (SELECT TOP (1) 
                            [Extent4].[Text] AS [Text]
                            FROM [fs].[TextAttributes] AS [Extent4]
                            WHERE ([Project4].[Id] = [Extent4].[FileRecordId]) AND ([Extent4].[ValidTo] IS NULL) AND ([Extent4].[CultureId] = @p__linq__2)) AS [C2]
                        FROM ( SELECT 
                            [Project3].[Id] AS [Id], 
                            [Project3].[Type] AS [Type], 
                            [Project3].[ParentId] AS [ParentId], 
                            [Project3].[C1] AS [C1]
                            FROM ( SELECT 
                                [Project1].[Id] AS [Id], 
                                [Project1].[Type] AS [Type], 
                                [Project1].[ParentId] AS [ParentId], 
                                (SELECT TOP (1) 
                                    [Extent3].[Title] AS [Title]
                                    FROM [fs].[FileTitleAttributes] AS [Extent3]
                                    WHERE ([Project1].[Id] = [Extent3].[FileRecordId]) AND ([Extent3].[ValidTo] IS NULL) AND ([Extent3].[CultureId] = @p__linq__1)) AS [C1]
                                FROM ( SELECT 
                                    [Extent1].[Id] AS [Id], 
                                    [Extent1].[Type] AS [Type], 
                                    [Extent2].[ParentId] AS [ParentId]
                                    FROM  [fs].[Files] AS [Extent1]
                                    INNER JOIN [fs].[LinkAttributes] AS [Extent2] ON [Extent1].[Id] = [Extent2].[FileRecordId]
                                    WHERE ((([Extent1].[BrandId] = @p__linq__0) AND (2 = [Extent1].[Type])) OR (5 = [Extent1].[Type])) AND ([Extent2].[ValidTo] IS NULL)
                                )  AS [Project1]
                            )  AS [Project3]
                        )  AS [Project4]
                    )  AS [Project6]
                )  AS [Project7]
            )  AS [Project9]
        )  AS [Project10]
    )  AS [Project12]

在所有三个表(TitleAttributes,TextAttributes和PublishedAttributes)中,所有键都相同,所有索引都相同,CF EF映射,都是相同的 - 但我不明白为什么生成的查询包含相同的选择两次。我困惑了几个小时后,一无所知。

EF6.1,.NET 4.6.1

编辑:我发现如果我选择的值是字符串,那么适当的SELECT就是正确的一次。否则,如果它是int或bool,则选择它两次。 titleAttr.Title和textAttr.Text是字符串; publishedAttr.Published是boolean - 所以它因某种原因被选中两次。怪异。

1 个答案:

答案 0 :(得分:0)

我终于发现/意识到当选择的值不可为空时问题就出现了,答案就在这里:

CASE WHEN ([Project12].[C3] IS NULL) THEN cast(0 as bit) ELSE [Project12].[C4] END AS [C4]

有必要找出值是否为空(第一次选择),如果是,返回0,如果不是,则返回值(第二次选择)。