【问题标题】:How to OrderBy using a child collection in lambda expression如何在 lambda 表达式中使用子集合进行排序
【发布时间】:2012-05-30 20:41:25
【问题描述】:

我有一个使用 lambda 表达式的查询,我希望能够从作为父表的子集合的表中的列进行排序。查询如下所示:

 var query = ctx.Timelines.Include("Rule.DocumentRules").Where(...).OrderBy(o => o.Rule.DocumentRules.OrderBy(t => t.SortOrder));

SortOrder 列位于时间线实体下方的 3 层深处,我不知道使用哪个扩展来访问它。当我使用上面的代码时,我收到一个错误“DbSortClause 表达式必须具有可与顺序比较的类型。 参数名称:key”。如果我使用 Select 扩展而不是 2nd OrderBy,我会遇到同样的错误。有人知道我如何按此列排序吗?此“SortOrder”列不是主键或外键。

谢谢

【问题讨论】:

  • 按整个子实体序列排序是荒谬的。只有将子实体集合并为一个值,然后可以用于排序,这才有意义。这可以通过选择单个实体(通过First())或使用聚合运算符(如MaxSum)来完成。
  • 您似乎要同时按多个事物排序?时间线和 documentRules 之间是否存在一对一的关系?

标签: c# asp.net entity-framework


【解决方案1】:

我知道这是一个旧帖子,但我遇到了这个帖子,因为我遇到了同样的问题,并且由于它没有答案,我想我会分享我的解决方案,以防它帮助其他人。

假设您需要显示实际的父母(即...妈妈/爸爸)和他们的孩子,但您想在报告中按字母顺序显示孩子的姓名。如果它们在数据库中的顺序不正确,则必须按子表上的“名称”字段对其进行排序,以根据要求显示它们。

按预期工作的简单 T-SQL 示例:

select * from ParentTable p
inner join ChildTable c on c.ParentId = p.ParentId
where p.ParentId = 1
order by c.Name

我曾尝试以与原始海报相同的方式完成此操作(如下所示)并得到“DbSortClause 表达式必须具有可与顺序比较的类型”异常。

.OrderBy(x => x.ParentTable.ChildTable.OrderBy(y => y.Name))

我正在使用投影,所以这可能不适用于所有人,但我发现如果我在子列表的投影中执行 OrderBy,它也可以按我的意愿工作。

Children = x.ParentTable.ChildTable.OrderBy(y => y.Name).Select(aa => new ChildTableModel

很可能有更好/不同的方法来实现这一点,但这正是我想要的,所以我想我会分享。

【讨论】:

    【解决方案2】:

    看起来您正在尝试按多个子项进行排序,这对编译器来说实际上没有意义。如果这两个实体之间确实存在一对一的关系,您可以尝试类似

    var query = ctx.Timelines.Include("Rule.DocumentRules").Where(...).OrderBy(o => o.Rule.DocumentRules.First().SortOrder));
    

    这可能会导致空异常,具体取决于您的数据库的设置方式。

    【讨论】:

    • 当我使用 First() 方法时,我得到“方法 'First' 只能用作最终查询操作。请考虑在此实例中使用方法 'FirstOrDefault'。” FirstOrDefault() 不会失败,但不会以正确的顺序返回它们。 TimeLine 和 DocumentRule 之间没有直接关系。一个时间线可以有一个规则,一个规则可以有多个 DocumentRules。 DocumentRule 表有一个我想在我的 OrderBy 中使用的 SortOrder 列。我可以像这样在 SQL 中实现这一点:
    • 对不起...被切断了。 select * from timeline t inner join [rule] r on t.ruleid = r.ruleid inner join documentrule d on t.ruleid = d.ruleid where order by d.sortorder 我应该说时间线可以有一个规则和一条规则可以存在于许多 DocumentRules 中。 DocumentRule 表是一个查找表,只是 Rule 表的一个子集。谢谢
    • 好的。如果给定时间线有 3 个不同的文档规则,我应该使用这三个中的哪一个来订购?如果我有 2 个不同的时间线,每个时间线都有 3 个不同的文档规则,那么现在我有九个单独的可排序项目,但我只尝试对两件事进行排序。因此,您必须编写一些内容来指定要按哪些文档规则进行排序。相反,您可以将排序顺序添加到时间线
    • 在大多数情况下,我只显示时间轴表中的信息,但如果有关联的文档条件,那么我需要链接到 DocumentRule 表以仅显示此表中列出的某些规则,我需要让它们按 Sortorder 列排序。因此,如果该表中有 7 条记录,我的 sortorder 列将相应地从 1 到 7 编号。
    • 我也没有意识到关于 First(),使用它或 FirstOrDefault() 将导致您选择第一个 documentRule。如果给定规则没有文档规则,则 First 和 FirstOrDefault() 都将导致 sortorder 上的引用为空
    【解决方案3】:

    我在尝试按相关实体中的列排序时遇到了同样的问题。唯一有效的解决方案是使用 Entity SQL。这是一个使用返回 ObjectQuery 的 ESQL 查询的简单示例:Converting ESQL to LINQ to Entities. Sort by related entities

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-11
      • 1970-01-01
      • 2014-03-10
      相关资源
      最近更新 更多