List<T>的实现丢失了原始查询中的排序

5

我使用Entity Framework得到一个Meeting数据库对象的IQueryable,并且eDbContext

IQueryable<Meeting> meetings = e.Meetings
    .Include(m => m.MeetingStage)
    .Include(m => m.MeetingType)

这个查询已经应用了 OrderBy

然后我想从这个查询中选择并创建一个新的对象 MeetingSearchResult。然而,在某些情况下,排序发生了改变,如下面的测试所示。

var temp2 = sortedMeetings.Select(m => m.MeetingID);

System.Diagnostics.Debug.WriteLine(string.Join(" / ", temp2.ToList().ToArray()));

var temp4 = sortedMeetings.Select(m => new MeetingSearchResult()
{
       MeetingID = m.MeetingID,
       CompanyName = m.CompanyName
});

System.Diagnostics.Debug.WriteLine(string.Join(" / ", temp4.ToList().Select(m => m.MeetingID).ToArray()));

var temp8 = sortedMeetings.Select(m => new MeetingSearchResult()
{
      MeetingID = m.MeetingID,
      CompanyName = m.CompanyName,
      MeetingDate = m.MeetingDate,
      MeetingStage = m.MeetingStage.Description
});

System.Diagnostics.Debug.WriteLine(string.Join(" / ", temp8.ToList().Select(m => m.MeetingID).ToArray()));

这里调试器的输出为:
2493 / 4228 / 7029 / 8254 / 9375 / 10563 / 11716 / 10500
2493 / 4228 / 7029 / 8254 / 9375 / 10563 / 11716 / 10500
2493 / 4228 / 7029 / 8254 / 9375 / 10500 / 10563 / 11716

temp8中对象的顺序已经改变。有人能解释一下吗?

更多信息:

有人要求关于sortedMeetings是什么的更多信息。

var sortedMeetings = meetings.DoMeetingSort(sort, ascending);

以下是我的扩展程序DoMeetingSort。我已经删除了不适用的switch cases:

    public static IQueryable<Meeting> DoMeetingSort(this IQueryable<Meeting> query, Constants.MeetingSortColumn column, bool ascending)
    {
        switch (column)
        {
            case Constants.MeetingSortColumn.MeetingType:
                return ascending
                    ? query.OrderBy(m => m.MeetingType.Description).ThenBy(m => m.MeetingDate).ThenBy(m => m.CompanyName)
                    : query.OrderByDescending(m => m.MeetingType.Description).ThenByDescending(m => m.MeetingDate).ThenByDescending(m => m.CompanyName);
        }
    }

你尝试过通过调用.ToList()枚举结果吗?为什么要尝试使用代理键对任何内容进行排序? - TGlatzer
你如何应用OrderBy?temp是什么?生成了哪些查询? - Sergey Berezovskiy
Meetings表是否应用了索引?选择另一组字段可能意味着数据库使用了另一个索引,这可能意味着另一种排序。 - Andrei
sortedMeetings是什么? - alexmac
添加了有关sortedMeetings的更多信息。 Meetings表除了主键MeetingID之外没有其他索引。 - Tom Troughton
2个回答

1
有很多原因会导致这种情况发生,但从您的示例中,最可能的原因是底层数据库决定了这一点。我假设您的sortedMeetings仍然是一个IQueryable,因此查询仍在构建中。随着您包含其他列并调用ToList(),不同的查询将被发送到您的数据库引擎,它可能会决定使用另一个索引或只是另一个路径来处理您的查询。如果您正在使用Sql Server,请分析您的查询并查看执行计划,但无论如何,在您想要的内容中使用OrderBy,这是您唯一的保证。
但请使用OrderBy呈现sortedMeetings以进行完整分析。
编辑:此外,似乎源IQueryable不同:temp2来源于sortedMeetingstemp4temp8来源于temp。此外,如果您正在使用EF6,请使用context.Database.Log来转储您的查询,否则请使用数据库分析器。在此处发布数据库查询,我们将帮助您进行分析。

我怀疑你是对的@saamorim,但这并没有让我感到困惑。我在很多地方都使用类似的逻辑,但即使经过彻底的测试,这仍然是唯一一个似乎丢失了顺序的地方。无论如何,我已经更新了我的原始问题,并希望得到你的意见。 - Tom Troughton

0
我找到了答案。我返回的MeetingSearchResult对象没有代表被排序列的属性,因此该列未包含在数据库查询中。这很明显,但让我困惑了很长时间。这也解释了为什么在其他列上排序正常工作。
+1给@saamorim,他作为一双新鲜的眼睛指向了我不知道的context.Database.Log

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接