我正在使用EF5并发现如下问题:
context.Questions
.OrderBy(x => Guid.NewGuid())
.Where(x => x.Difficulty == difficulty && x.Format == format);
每个问题都有一个名为duration的字段,其值为(2,4,6和8),以分钟为单位。
我有以下int数组:{4,0,1,2},表示:
得到2分钟,4分钟0分钟,6分钟1分钟和8分钟2分钟的4个问题。
之后.OrderBy和。我需要提到7个问题。
有没有办法在不加载所有问题或使用4个查询的情况下执行此操作?
谢谢你, 米格尔
答案 0 :(得分:1)
这是一种硬编码 - 但你明白了,并明确地解决了你的问题。你应该能够从这里将它转换成你需要的任何东西。
var questions = context.Questions .OrderBy(x => Guid.NewGuid())
.Where(x => x.Difficulty == difficulty && x.Format == format);
var selectedQuestions = questions.Where(q => q.Duration == 2).Take(questionArray[0])
.Union(questions.Where(q => q.Duration == 4).Take(questionArray[1]))
.Union(questions.Where(q => q.Duration == 6).Take(questionArray[2]))
.Union(questions.Where(q => q.Duration == 8).Take(questionArray[3]));
由于您永远不会枚举可查询,因此EF将在sql中执行所有这些联合,并在一次调用中获取所有数据。
制作SQL:
SELECT [Distinct3].[C1] AS [C1],
[Distinct3].[C2] AS [C2],
[Distinct3].[C3] AS [C3],
[Distinct3].[C4] AS [C4]
FROM (SELECT DISTINCT [UnionAll3].[C1] AS [C1],
[UnionAll3].[C2] AS [C2],
[UnionAll3].[C3] AS [C3],
[UnionAll3].[C4] AS [C4]
FROM (SELECT [Distinct2].[C1] AS [C1],
[Distinct2].[C2] AS [C2],
[Distinct2].[C3] AS [C3],
[Distinct2].[C4] AS [C4]
FROM (SELECT DISTINCT [UnionAll2].[C1] AS [C1],
[UnionAll2].[C2] AS [C2],
[UnionAll2].[C3] AS [C3],
[UnionAll2].[C4] AS [C4]
FROM (SELECT [Distinct1].[C1] AS [C1],
[Distinct1].[C2] AS [C2],
[Distinct1].[C3] AS [C3],
[Distinct1].[C4] AS [C4]
FROM (SELECT DISTINCT [UnionAll1].[Id] AS [C1],
[UnionAll1].[Duration] AS [C2],
[UnionAll1].[Difficulty] AS [C3],
[UnionAll1].[Format] AS [C4]
FROM (SELECT TOP (4) [Project1].[Id] AS [Id],
[Project1].[Duration] AS [Duration],
[Project1].[Difficulty] AS [Difficulty],
[Project1].[Format] AS [Format]
FROM (SELECT NEWID() AS [C1],
[Extent1].[Id] AS [Id],
[Extent1].[Duration] AS [Duration],
[Extent1].[Difficulty] AS [Difficulty],
[Extent1].[Format] AS [Format]
FROM [dbo].[Questions] AS [Extent1]
WHERE ([Extent1].[Difficulty] = @p__linq__0)
AND ([Extent1].[Format] = @p__linq__1)
AND (2 = [Extent1].[Duration])) AS [Project1]
ORDER BY [Project1].[C1] ASC
UNION ALL
SELECT TOP (0) [Project3].[Id] AS [Id],
[Project3].[Duration] AS [Duration],
[Project3].[Difficulty] AS [Difficulty],
[Project3].[Format] AS [Format]
FROM (SELECT NEWID() AS [C1],
[Extent2].[Id] AS [Id],
[Extent2].[Duration] AS [Duration],
[Extent2].[Difficulty] AS [Difficulty],
[Extent2].[Format] AS [Format]
FROM [dbo].[Questions] AS [Extent2]
WHERE ([Extent2].[Difficulty] = @p__linq__2)
AND ([Extent2].[Format] = @p__linq__3)
AND (4 = [Extent2].[Duration])) AS [Project3]
ORDER BY [Project3].[C1] ASC) AS [UnionAll1]) AS [Distinct1]
UNION ALL
SELECT TOP (1) [Project7].[Id] AS [Id],
[Project7].[Duration] AS [Duration],
[Project7].[Difficulty] AS [Difficulty],
[Project7].[Format] AS [Format]
FROM (SELECT NEWID() AS [C1],
[Extent3].[Id] AS [Id],
[Extent3].[Duration] AS [Duration],
[Extent3].[Difficulty] AS [Difficulty],
[Extent3].[Format] AS [Format]
FROM [dbo].[Questions] AS [Extent3]
WHERE ([Extent3].[Difficulty] = @p__linq__4)
AND ([Extent3].[Format] = @p__linq__5)
AND (6 = [Extent3].[Duration])) AS [Project7]
ORDER BY [Project7].[C1] ASC) AS [UnionAll2]) AS [Distinct2]
UNION ALL
SELECT TOP (2) [Project11].[Id] AS [Id],
[Project11].[Duration] AS [Duration],
[Project11].[Difficulty] AS [Difficulty],
[Project11].[Format] AS [Format]
FROM (SELECT NEWID() AS [C1],
[Extent4].[Id] AS [Id],
[Extent4].[Duration] AS [Duration],
[Extent4].[Difficulty] AS [Difficulty],
[Extent4].[Format] AS [Format]
FROM [dbo].[Questions] AS [Extent4]
WHERE ([Extent4].[Difficulty] = @p__linq__6)
AND ([Extent4].[Format] = @p__linq__7)
AND (8 = [Extent4].[Duration])) AS [Project11]
ORDER BY [Project11].[C1] ASC) AS [UnionAll3]) AS [Distinct3];
答案 1 :(得分:0)
为什么不只是获得每种类型的4个(或最大数组)问题并在客户端上进行过滤?有16个结果它应该很便宜 - 你可以使用linq分组按分钟分组,然后它应该很容易。这里另一个有趣的点是订购...如果你有超过4个问题,但你总是在选择时订购它们,你会看到任何其他问题只是前4个吗?
答案 2 :(得分:0)
我的查询有点复杂。基本上,我最终得到以下结论:
context.Questions
.OrderBy(x => Guid.NewGuid())
.Where(x =>
x.AccessLevel >= accessLevel &&
x.Enabled == true &&
x.QuestionFormat == questionFormat
x.Theme.Id == themeId
)
.Select(x => new {
Answers = x.Answers.Select(y => new {
Correct = y.Correct,
Packs = y.Packs.SelectMany(z => z.Files, (z, v) => new {
Id = z.Id,
File = new { Key = v.Key, Mime = v.Mime }
}),
Text = y.Text
}),
Duration = x.Duration,
Note = x.Note,
Text = x.Text,
Packs = x.Packs.SelectMany(y => y.Files, (y, z) => new {
Id = y.Id,
File = new { Key = z.Key, Mime = z.Mime }
})
})
.GroupBy(x => x.Duration);
所以我随机排序并过滤它们。
然后,对于每个问题,我得到答案......
每个问题和答案都有一些与之相关的文件。
我将所有文件都放在一个表中。这就是我在查询中有包和文件的原因。
我只加载文件密钥和哑剧。不是数据。
所以你的建议是按时间分组所有问题,对吗?
事实上,在执行AccessLevel / Enabled / QuestionFormat / Theme过滤后,我将永远不会有这么多问题......
所以我可以按照我在查询结束时的持续时间对它们进行分组。
根据我在开头发布的数组,采用每个持续时间的问题数量的快速方法是什么?
谢谢你, 米格尔