2

我正在重写一个需要复制旧大型机系统的字母排序逻辑的应用程序。在旧的大型机系统中,项目更改记录 ID 按字母顺序从 A 到 Z,然后以 AA、AB 等重新开始。不幸的是,SQL Server 和 .NET 都希望将 AA 放在 A 和 B 之间,所以我不得不跳过一些障碍。我试图先按长度降序对更改 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 的行,实际上,当我注释掉带有 orderbys 的行时,我得到的结果与我得到的 Linqpad(使用默认配置)相同。SQL Profiler 显示生成的 SQL 几乎不可能被人类破译,但它的任何地方都不包含“order”一词。

最后一点,当我将 Linqpad 配置为在项目程序集中使用我的 EF 生成的类型化数据集时,我得到的结果与我在运行时看到的结果相同,结果似乎忽略了 orderbys。

我希望我能显示实际结果,但数据是专有的,所以只需考虑 Linqpad 和我的单元测试提供的正确结果,包含带有“Y”和“Z”等 ID 的更改记录,其中无法解释(对我来说) 我在运行时在项目中看到的结果类似于“A”和“B”。

谁能看到这里发生了什么,同样重要的是,我需要改变什么才能使这个功能达到我的预期?

我的项目使用的是实体框架 5.0,我使用的是 Linqpad 4.42.01。

非常感谢!

4

2 回答 2

4

Group by 不保证保留原始订单。如果你想订购,你必须在group by之后订购。

事实上,在 group by 之前 order by 甚至没有意义,因为 group by 保证会更改顺序(除非只有一个组)。

于 2012-10-02T18:19:20.497 回答
0

I'll make a wild guess...

Your ChangeId's are all the same length. The database has them mapped as a CHAR(10) column or something instead of a VARCHAR, so A is really "A " and AB is really "AB ". Mainframes and COBOL and flat files with offsets come to mind as my rationale. If this is the case you'd have to Trim() the ChangeId first before getting the Length.

于 2012-10-02T18:34:37.750 回答