实体框架......将四个查询合二为一

时间:2013-03-05 12:05:42

标签: entity-framework

我正在使用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个查询的情况下执行此操作?

谢谢你, 米格尔

3 个答案:

答案 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过滤后,我将永远不会有这么多问题......

所以我可以按照我在查询结束时的持续时间对它们进行分组。

根据我在开头发布的数组,采用每个持续时间的问题数量的快速方法是什么?

谢谢你, 米格尔