2

Я пытался реализовать естественную сортировку с помощью LINQ для лиц, используя эквивалент этого SQL заявления:Естественная сортировка с помощью LINQ к Entities

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

Мой LINQ запрос является:

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

LINQ к Entities, хотя добавляет тильду (~) в шаблоне.

Это генерации 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 

Как я могу удалить тильды (~), которая была прилагаемую после, как '~ [0-9]%'?

+0

Вы не потому, что нет ничего плохого. '[' - специальный символ, который нуждается в экранировании, и это то, что делает EF. Запрос правильный, как есть. Вы просили имена, начинающиеся с точной строки '[0-9]'. Если вы не получаете результаты, это потому, что нет строки, которая начинается с точной строки '[0-9]' –

+0

. Я получаю результат в sql-сервере после удаления добавленной тильды (~). Его не сбежали. – Aby

+1

В запросе запрашиваются имена, начинающиеся с '[0-9]' ** ТОЧНО **. Вы запрашиваете '[0-9] George' и' [0-9] Pete', а не '0George'. Удалив escape-символ, вы выполняете совершенно другой запрос. Вы не можете использовать сопоставление с шаблоном 'StartsWith'. Вы пытались найти имена, начинающиеся с числа? –

ответ

3

Нет ничего плохого в сгенерированном запросе, это точно так, как должно быть. В запросе запрашиваются имена, начинающиеся с точной строки [0-9].

String.StartsWith(x) is string метод, который проверяет, начинается ли строка с литерала, без соответствия шаблону. Linq to Entities переводит этот LIKE 'x%', где x - это буквальная строка, а не шаблон. [ - особый символ в инструкции LIKE. Это означает, что он должен быть экранирован с помощью LIKE '~[0-9]%' escape '~'. Оператор LIKE позволяет указать escape-символ, в данном случае ~.

Я подозреваю, что вам не нужны имена, начинающиеся с [0-9], но те, которые начинаются с цифры, то есть LIKE '[0-9]%'. String.StartsWith не поддерживает шаблоны и не существует другого метода String.

Одним из решений является использование SqlFunctions.PatIndex в вашем запросе и фильтр для возвращаемых строк 1. Я бы проверял план выполнения, потому что я подозреваю, что запрос будет медленнее. LIKE '[0-9]% - это поиск по всем строкам, начинающимся с 0 вплоть до буквы после 9 исключая, т. Е. A. Это означает, что сервер может использовать индексы на Name. С PATINDEX, возможно, придется обрабатывать все строки.

К сожалению, SqlFunctions не содержит Like или любой аналогичный метод, который бы сгенерировал оператор LIKE с сопоставлением с образцом.

Другой вариант - фактически запросить запрос диапазона с помощью a.Name >="0" && a.Name <"A".

ОБНОВЛЕНИЕ - ПРИРОДНЫЙ SORTING

Это случай XY Problem. Фактическая проблема X заключается в том, как выполнять естественную сортировку с помощью LINQ to Entities. Одним из решений T-SQL для естественной сортировки является использование формулы в ORDER BY пункта в сочетании с самого именем, чтобы цифры появляются после того, как простой текст, например:

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

К сожалению, это Безразлично Не работайте с EF, потому что нет эквивалента LIKE с узорами.

То же заказ может быть выполнен с PATINDEX, который является доступный через функцию SqlFunctions.PatIndex:

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

Эквивалентный код LINQ может быть:

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

Спасибо Panagiotis, PatIndex работал здесь :) – Aby

Смежные вопросы