Структура объекта OrderBy "CASE WHEN"

Мне интересно, если кто-то знает, как выразить в Entity Framework то, что будет в чистом SQL:

SELECT Name, IsEmployee, IsQualityNetwork
FROM Person
ORDER BY CASE WHEN IsQualityNetwork = 1 or IsEmployee = 1 THEN 0 ELSE 1 END, Name

Я пробовал использовать Linq Dynamic, но когда этот код выполняется:

var p = ctx.People
    .OrderBy("CASE WHEN IsQualityNetwork = 1 or IsEmployee = 1 THEN 0 ELSE 1 END")
    .OrderBy(e => e.Name);

Я получаю исключение: { "Нет свойства или поля" CASE "существует в типе" Лицо ""}

Ответ 1

var p = ctx.People.OrderBy(p => (p.IsQualityNetwork == 1 || p.IsEmployee == 1) ? 0 : 1)
                  .ThenBy(p => p.Name);

Ответ 2

Вот перевод вашего SQL в LINQ.

var query = from p in ctx.People
            let order = p.IsQualityNetwork || p.IsEmployee ? 0 : 1
            orderby order, p.Name
            select new
            {
                p.Name,
                p.IsEmployee,
                p.IsQualityNetwork,
            }

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

Ответ 3

Я создал метод расширения с пользовательской функцией порядка сортировки. он также работает с Entity Framework, передавая порядок в sql как ORDER BY CASE WHEN..THEN.. просто передайте возвращенное выражение из этого метода в параметр метода .OrderBy()

public static Expression<Func<TEntity, int>> CustomSortOrder<TEntity>(this IList<string> customSortOrderValues, string propName) {

var e = Expression.Parameter(typeof(TEntity), "e");
var prop = typeof(TEntity).GetProperty(propName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
var eDotProp = Expression.MakeMemberAccess(e, prop);
var maxLen = customSortOrderValues.Count;

Expression ElseExpression(IList<string> values) {
    var value = values[0];
    var condition = Expression.Equal(eDotProp, Expression.Constant(value));
    var ifTrue = Expression.Constant(maxLen - values.Count);
    Expression ifFalse ;

    if (values.Count == 1) {
        ifFalse = Expression.Constant(maxLen - values.Count + 1);
    }
    else {
        values.RemoveAt(0);
        ifFalse = ElseExpression(values);
    }
    return Expression.Condition(condition, ifTrue, ifFalse);
}

return Expression.Lambda<Func<TEntity, int>>(
    ElseExpression(customSortOrderValues),
    e);
}

и сказать, что наша модель:

public class Cat{
public string Name {get;set;}
public Cat(string name){
        Name = name;
}

использование...

var cats = new List<Cat> { new Cat("cat1"), new Cat("cat2"), new Cat("cat3") };
var customSortExpression = new List<string> { "cat2", "cat1", "cat3" }.CustomSortOrder<Cat>("Name");
var customOrderCats = cats.AsQueryable().OrderBy(customSortExpression); // works with Entity framework too //orders cat2,cat1,cat3