LINQ .OrderBy создает вложенный корпус - PullRequest
1 голос
/ 11 апреля 2019

Я пытаюсь запросить таблицу и вернуть строки в указанном пользовательском порядке на основе столбца состояния.

Это очень простой запрос SQL:

SELECT  * From Table1
WHERE Id = 1
ORDER by CASE 
      WHEN [Status] = 'Status1' THEN 1
      WHEN [Status] = 'Status2' THEN 2
      WHEN [Status] = 'Status3' THEN 3
      WHEN [Status] = 'Status4' THEN 4
      WHEN [Status] = 'Status5' THEN 5
      WHEN [Status] = 'Status6' THEN 6
      WHEN [Status] = 'Status7' THEN 7
      WHEN [Status] = 'Status8' THEN 8
      WHEN [Status] = 'Status9' THEN 9
      WHEN [Status] = 'Satus10' THEN 10
      WHEN [Status] = 'Status11' THEN 11
      ELSE [Status] END ASC

Я пытаюсь выполнить тот же запрос, используя LINQ.

var data = _myContext.Table1.Where(l => l.Id == 1).Select(lp =>
            new DataModel
            {
                Id = lp.Id,
                Status = lp.Status,
                ...
            })
            .OrderBy(l => 
                       l.Status == StatusEnum.Status1.ToString() ? 1 : 
                       l.Status == StatusEnum.Status2.ToString() ? 2 : 
                       l.Status == StatusEnum.Status3.ToString() ? 3 : 
                       l.Status == StatusEnum.Status4.ToString() ? 4 : 
                       l.Status == StatusEnum.Status5.ToString() ? 5 : 
                       l.Status == StatusEnum.Status6.ToString() ? 6 : 
                       l.Status == StatusEnum.Status7.ToString() ? 7 : 
                       l.Status == StatusEnum.Status8.ToString() ? 8 : 
                       l.Status == StatusEnum.Status9.ToString() ? 9 : 
                       l.Status == StatusEnum.Status10.ToString() ? 10 : 
                       l.Status == StatusEnum.Sattus11.ToString() ? 11 : 0
            );

Но этот запрос не выполняется с:

Выражения регистра могут быть вложены только до уровня 10.

Глядя на профилировщик, я вижу, что EF создает следующий запрос, который в свою очередь дает сбой, поскольку у меня указано более 10 значений:

exec sp_executesql N'SELECT [l].[Id],[l].[Status], ...
FROM [Table1] AS [l]
WHERE [l].[Id] = @__id_0
ORDER BY CASE
    WHEN [l].[Status] = @__ToString_1
    THEN 1 ELSE CASE
        WHEN [l].[Status] = @__ToString_2
        THEN 2 ELSE CASE
            WHEN [l].[Status] = @__ToString_3
            THEN 3 ELSE CASE
                WHEN [l].[Status] = @__ToString_4
                THEN 4 ELSE CASE
                    WHEN [l].[Status] = @__ToString_5
                    THEN 5 ELSE CASE
                        WHEN [l].[Status] = @__ToString_6
                        THEN 6 ELSE CASE
                            WHEN [l].[Status] = @__ToString_7
                            THEN 7 ELSE CASE
                                WHEN [l].[Status] = @__ToString_8
                                THEN 8 ELSE CASE
                                    WHEN [l].[Status] = @__ToString_9
                                    THEN 9 ELSE CASE
                                        WHEN [l].[Status] = @__ToString_10
                                        THEN 10 ELSE CASE
                                            WHEN [l].[Status] = @__ToString_11
                                            THEN 11 ELSE 0
                                        END
                                    END
                                END
                            END
                        END
                    END
                END
            END
        END
    END
END',N'@__id_0 int,@__ToString_1 nvarchar(4000),@__ToString_2 nvarchar(4000),@__ToString_3 nvarchar(4000),@__ToString_4 nvarchar(4000),@__ToString_5 nvarchar(4000),@__ToString_6 nvarchar(4000),@__ToString_7 nvarchar(4000),@__ToString_8 nvarchar(4000),@__ToString_9 nvarchar(4000),@__ToString_10 nvarchar(4000),@__ToString_11 nvarchar(4000)',@__id_0=1,@__ToString_1=N'Status1',@__ToString_2=N'Status2',@__ToString_3=N'Status3',@__ToString_4=N'Status4',@__ToString_5=N'Status5',@__ToString_6=N'Status6',@__ToString_7=N'Status7',@__ToString_8=N'Status8',@__ToString_9=N'Status9',@__ToString_10=N'Status10',@__ToString_11=N'Status11'

Есть ли способ написать этот запрос, чтобы он не использовал ELSE CASE и просто соответствовал вышеуказанному запросу SQL?

У меня есть несколько вариантов, чтобы обойти это. Напишите хранимую процедуру и получите нужный мне вывод или сохраните запрос в списке без OrderBy и упорядочите список. Но я очень стараюсь увидеть, есть ли способ сделать это в этом запросе.

Ответы [ 2 ]

2 голосов
/ 11 апреля 2019

Это известное текущее ограничение EF Core, отслеживаемое # 12729 Выравнивать выражения CASE, чтобы избежать ошибки "Выражения регистра могут быть вложены только до уровня 10" .

К сожалению, не запланированорешаться вообще и обходного пути не предусмотрено.Также использование преобразователя значений не работает.

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

0 голосов
/ 11 апреля 2019

Этот ответ не является LINQ за слово, но если вы создаете вычисляемый столбец, который соответствует вашему CASE, вы можете отсортировать по этому столбцу. Вы можете использовать функции в вычисляемом столбце, и если эта функция проста, столбец может быть сохранен и проиндексирован.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...