【问题标题】:How to order by 1 expression or 2 expressions based on a condition?如何根据条件按 1 个表达式或 2 个表达式排序?
【发布时间】:2018-05-31 23:45:33
【问题描述】:

我在一个结果中显示企业和人员,并希望将它们一起订购。

伪代码:

if business name is not null
order by business name
else
order by first name then last name

我构建了 LINQ 查询,它连接到多个表(并且工作正常),大致如下所示。

var query = from x in ...
    join business in dbContext.Businesses on ...
    from businesses in bus.DefaultIfEmpty()
    join person in dbContext.People on ...
    from people in peo.DefaultIfEmpty()
    select new Party
    {
        person.FirstName,
        person.LastName,
        business.Name,
    };

我不知道如何编写一个 LINQ 表达式,如果记录是企业,则仅按企业名称排序,否则人名和姓氏。我能得到的最接近的是以下内容,其中始终包括按人的姓氏排序(即使对于企业也是如此)。

var result =
    whereQuery
        .OrderBy(x => x.BusinessName != null ? x.BusinessName : x.PersonFirstName)
        .ThenBy(x => x.PersonLastName);

转换成 SQL:

ORDER BY CASE
    WHEN [business].[Name] IS NOT NULL
    THEN [business].[Name]
    ELSE [person].[FirstName]
END, [person].[LastName]

我想要的是:

ORDER BY CASE
    WHEN [business].[Name] IS NOT NULL
    THEN [business].[Name]
    ELSE [person].[FirstName], [person].[LastName]
END

这是我希望能够写的(显然错误部分的语法不正确):

var result =
        whereQuery
            .OrderBy(x => x.BusinessName != null ? x.BusinessName : x.PersonFirstName, x.PersonLastName);

从技术上讲,它并没有太大的区别(如果是企业,则人名和姓氏将为空,因此不应该影响顺序)。但 SQL 仍会尝试通过它不需要做的事情进行排序。

【问题讨论】:

    标签: c# linq .net-core entity-framework-core


    【解决方案1】:
    var result =
      whereQuery
        .OrderBy(x => x.BusinessName != null ? x.BusinessName : x.PersonFirstName)
        .ThenBy(x => x.BusinessName != null ? x.BusinessName : x.PersonLastName);
    

    BusinessName 不为空的情况下会有冗余的二阶排序,但查询分析器(解析 SQL 后的下一步)应该能够删除该冗余。

    【讨论】:

    • 我最喜欢这个,因为ThenBy 不会对企业造成伤害(正如您所提到的),而且您不需要修改查询本身。请注意,ThenBy 无论如何都只需要订购领带。
    • @DavidSpence 是的。查询分析器的输出是什么样的?
    • 对不起,我按回车太快了。这会产生两个案例陈述,但正如你所说,可能有一些优化。我会检查一下。当 [o].[Name] IS NOT NULL THEN [o].[Name] ELSE [b].[LastName] END 时按大小写排序,当 [o].[Name] 不为 NULL THEN [o].[姓名] ELSE [b].[名字] END
    • @DavidSpence:当然,这些优化是由数据库而不是实体框架完成的。该 sql 将被发送到 rdbms。但即使数据库是愚蠢的,这也不会受到伤害。结果将是相同的,并且仅在领带上应用额外的排序(如果企业名称重复)。
    【解决方案2】:

    像这样修改你的代码:

    var query = from x in ...
        join business in dbContext.Businesses on ...
        from businesses in bus.DefaultIfEmpty()
        join person in dbContext.People on ...
        from people in peo.DefaultIfEmpty()
        select new Party
        {
            Name = business.Name ?? person.FirstName,
            person.LastName
        };
    
    var result = whereQuery
            .OrderBy(x => x.Name)
            .ThenBy(x => x.PersonLastName);
    

    选择名称并确保它不为空,然后按此字段排序。

    【讨论】:

    • 我认为这相当于我的代码,除了空检查在不同的地方?看起来它仍将始终包含按人姓的顺序,即使对于企业也是如此。
    猜你喜欢
    • 1970-01-01
    • 2020-07-14
    • 2021-12-24
    • 2013-12-22
    • 2016-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-07
    相关资源
    最近更新 更多