2015-07-01 2 views
0

У меня есть объект IQueryable<...>, который является запросом LINQ-to-SQL, который я пытаюсь заказать по имени в алфавитном порядке, но с цифрами после букв (az, 0-9 вместо 0-9, az). Например, список:Пользовательский заказ строковых значений в запросе LINQ-to-SQL

1st Street 
Zeta 
2nd Street 
Alpha 

Должны быть заказаны как:

Alpha 
Zeta 
1st Street 
2nd Street 

В настоящее время у меня есть следующий код:

IQueryable<...> holdings = ...; 
/* ... */ 
return holdings.OrderBy(q => q.Name); 

Но это упорядочивает элементы следующим образом:

1st Street 
2nd Street 
Alpha 
Zeta 

Любые мысли s о том, как заказать этот IQueryable желаемым образом?

+4

Предоставьте свой собственный «IComparer» и используйте [эту перегрузку «OrderBy'] (https://msdn.microsoft.com/en-us/library/vstudio/bb549422 (v = vs.100) .aspx) – ryanyuyu

+0

Кроме того, это сравнение чувствительно к регистру? Или он обрабатывает только английские буквы или цифры? – ryanyuyu

+2

@ryanyuyu Он использует 'Queryable.OrderBy' не' Enumerable.OrderBy', так что это не вариант. – Servy

ответ

1

Нечто подобное должно работать, с оговоркой, что вам нужно будет изменить класс вашего объекта или создать новый anonymous type.

Он по существу помещает символ пробела перед любым именем, которое не начинается с числа, а затем заказы на это. Пробелы обычно сортируются перед числами в SQL-заказе.

holdings.Select(h => new { 
    name = h.name, 

    /* copy all other fields you need here */ 

    // select a new field specifically for ordering. 
    orderingName = SqlMethods.Like(q.name, "[^0-9]%") ? " " + q.name : q.name 
}).OrderBy(q => q.orderingName); 

Я довольно уверен, что есть некоторые серьезные проблемы с производительностью, которые могут возникнуть из-за CASE заявления это будет генерировать. Вероятно, вы можете решить проблему лучше, предварительно вычислив имя сортировки заблаговременно и просто сохранив ее в базе данных, а затем отсортировать и индексировать ее.

0

Ну, если вы готовы отказаться от части Iqueryable, вы можете сделать .ToList() и сделать остальное в памяти.

Другой вариант я вижу бы сделать двойное OrderBy:

Первый OrderBy() сходил на первый символ Второй ThenBy() на всей имени

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