为什么Entity Framework无视我的订单?

时间:2012-10-02 18:12:01

标签: linqpad entity-framework-5

我正在重写一个需要复制旧主机系统的字母顺序逻辑的应用程序。在旧的主机系统中,项目更改记录ID从A到Z按字母顺序排列,然后从AA,AB等开始。不幸的是,SQL Server和.NET都希望在A和B之间放置AA,所以我不得不跳过一些箍。我正在尝试先按降序长度排序更改ID,然后按降序按字母顺序排序。

以下是我用来检索数据的方法:

protected internal IList<TeamViewModel> GetTeams(string recordId, string changeId)
{
    var viewModels = (from x in repository.Teams
               where x.RecordId == recordId && x.ChangeId.Length <= changeId.Length && 
                 (x.ChangeId.CompareTo(changeId) == -1 || x.ChangeId.CompareTo(changeId) == 0)
               orderby x.ChangeId.Length descending, x.ChangeId descending, x.ChangeId descending
               group x by x.TeamId into grp
               select grp.FirstOrDefault())
               .ToList()
               .Select(TeamViewModel.FromEntity)
               .ToList();

            return viewModels;
}

每个“记录”都有一组变更记录,每个变更记录一次ChangeId属性和进行更改的TeamId。我正在尝试获得每个不同teamId的“最新”(根据旧的主机排序逻辑)更改记录。换句话说,我试图订购记录,按团队分组,然后从每个组中获取第一条记录。

repository.Teams属性返回一个IQueryable,它包装在ObjectContext中声明的ObjectSet。

真正让我感到震惊的是,当我在Linqpad中运行它时,此查询正常工作(默认配置)当我注入了一个模拟我的单元测试时,这个方法执行正常存储库到此类,我已设置为发出与SQL数据库中完全相同的数据。

但是当这个方法在运行时执行时,它的行为似乎完全省略了orderbys的行,并且实际上给了我相同的结果,当我用它注释掉行时我用Linqpad(默认配置) orderbys。 SQL事件探查器显示生成的SQL几乎不可能由人解密,但在任何地方都不包含“order”一词。

最后要注意的是,当我将Linqpad配置为在项目的程序集中使用我生成的EF类型数据集时,我得到的结果与我在运行时看到的结果相同,结果看起来好像忽略了orderbys。

我希望我能显示实际结果,但数据是专有的,所以只要考虑Linqpad和我的单元测试提供的正确结果,包含ID为“Y”和“Z”的更改记录,其中莫名其妙(对我而言)我在项目中在运行时看到的结果就像“A”和“B”。

任何人都可以看到这里发生了什么,同样重要的是,我需要改变什么来实现我期待的功能?

我的项目正在使用实体框架5.0,而我正在使用Linqpad 4.42.01。

非常感谢!

2 个答案:

答案 0 :(得分:4)

Group by不保证保留原始订单。如果您想订购,您必须在分组后订购。

事实上,在分组之前按顺序排序甚至没有意义,因为分组依据保证更改顺序(除非只有一个组)。

答案 1 :(得分:0)

我会猜测......

你的ChangeId都是一样的长度。数据库将它们映射为CHAR(10)列或其他东西而不是VARCHAR,因此A实际上是“A”而AB实际上是“AB”。作为我的理由,我想到了具有偏移的大型机和COBOL以及平面文件。如果是这种情况,你必须在获得长度之前首先修改()ChangeId。