简体   繁体   English

使用LINQ对实体进行自然排序

[英]Natural sorting with LINQ to Entities

I've tried to implement natural sorting with LINQ to Entities, using the equivalent of this SQL statement: 我试图使用LINQ to Entities来实现自然排序,使用此SQL语句的等效项:

ORDER BY case when name like '[0-9]%' then 1 else 0 end, name

My LINQ query is: 我的LINQ查询是:

query.OrderByDescending(a => a.Name.StartsWith("[0-9]") ? 1 : 0)

LINQ to Entities though is adding a tilde (~) in the pattern. LINQ to Entities在模式中添加了波浪号(〜)。

It's generating an SQL query like this: 它正在生成这样的SQL查询:

SELECT CASE WHEN (Extent1.name LIKE '~[0-9]%'  escape '~') THEN 1 ELSE 0 END AS [C1], name
        from accounts extent1
         order by c1 asc

How can I remove tilde (~) that has been appended after, like '~[0-9]%' ? 如何删除后面附加了波浪号(〜),例如'〜[0-9]%'

There's nothing wrong with the generated query, it's exactly as it should be. 生成的查询没有任何问题,完全正确。 Your query asks for names that start with the exact string [0-9] . 您的查询要求输入以精确字符串[0-9]开头的名称。

String.StartsWith(x) is a string method that checks whether a string starts with a literal, without pattern matching. String.StartsWith(x)是一个字符串方法,该方法检查字符串是否以文字开头而不进行模式匹配。 Linq to Entities translates this LIKE 'x%' where x is a literal string, not a pattern. Linq to Entities会转换此LIKE 'x%' ,其中x是文字字符串,而不是模式。 [ is a special character in a LIKE statement though. [尽管是LIKE语句中的特殊字符。 This means that it has to be escaped with LIKE '~[0-9]%' escape '~' . 这意味着必须使用LIKE '~[0-9]%' escape '~'对其进行转义。 The LIKE operator allows you to specify the escape character, in this case ~ . LIKE运算符允许您指定转义字符,在这种情况下为~

I suspect that you didn't want names starting with [0-9] though, but those that start with a digit, ie LIKE '[0-9]%' . 我怀疑您虽然不希望名称以[0-9]开头,但是希望以数字开头,例如LIKE '[0-9]%' String.StartsWith doesn't support patterns nor is there another String method that does. String.StartsWith不支持模式,也没有其他String方法支持。

One solution is to use SqlFunctions.PatIndex in your query and filter for rows that return 1. I'd check the execution plan though, because I suspect the query will be slower. 一种解决方案是在查询中使用SqlFunctions.PatIndex并过滤返回1的行。但是我会检查执行计划,因为我怀疑查询会变慢。 LIKE '[0-9]% is essentially a range search for all strings that start from 0 up to the letter after 9 excluding, ie A . LIKE '[0-9]%本质上是对从09之后(不包括A的所有字母的所有字符串进行范围搜索。 This means that the server can use indexes on Name . 这意味着服务器可以在Name上使用索引。 With PATINDEX it may have to process all rows. 使用PATINDEX可能必须处理所有行。

Unfortunately, SqlFunctions doesn't contain Like or any similar method that would generate a LIKE statement with pattern matching. 不幸的是, SqlFunctions不包含Like或任何其他会生成具有模式匹配的LIKE语句的方法。

Another option is to actually ask for a range query with a.Name >="0" && a.Name <"A" . 另一个选择是实际要求a.Name >="0" && a.Name <"A"的范围查询。

UPDATE - NATURAL SORTING 更新-自然排序

This is a case of the XY Problem . 这是XY问题的情况 The actual problem X is how to perform natural sorting with LINQ to Entities. 实际的问题X是如何使用LINQ对实体进行自然排序。 One of the T-SQL solutions for natural sorting is to use a formula in the ORDER BY clause in combination with the name itself , to make numbers appear after plain text, eg: 用于自然排序的T-SQL解决方案之一是将ORDER BY子句的公式与名称本身结合使用 ,以使数字出现在纯文本之后,例如:

ORDER BY case when name like '[0-9]%' then 1 else 0 end, name

Unfortunately, this doesn't work with EF because there is no equivalent to LIKE with patterns. 不幸的是,这不适用于EF,因为没有等效于LIKE的模式。

The same ordering can be performed with PATINDEX, which is available through the SqlFunctions.PatIndex function : 相同的排序可以用PATINDEX,这可通过SqlFunctions.PatIndex函数来执行:

order by name, case when PATINDEX('[0-9]%',name)=1 then 1 else 0 end

The equivalent LINQ code could be: 等效的LINQ代码可以是:

query.OrderBy(a => {
                     SqlFunctions.PatIndex("[0-9]%",a.Name)==1? 1:0,
                     a.Name
                   })

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM