我有这个简单的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 - 所以它因某种原因被选中两次。怪异。
答案 0 :(得分:0)
我终于发现/意识到当选择的值不可为空时问题就出现了,答案就在这里:
CASE WHEN ([Project12].[C3] IS NULL) THEN cast(0 as bit) ELSE [Project12].[C4] END AS [C4]
有必要找出值是否为空(第一次选择),如果是,返回0,如果不是,则返回值(第二次选择)。