EF.Core 3.x генерирует оконную функцию вместо JOIN, что приводит к синтаксической ошибке MySQL - PullRequest
0 голосов
/ 25 марта 2020

Выполнение следующего запроса EF Core:

var groupData = await _dbContext.Groups.AsNoTracking()
    .Where(g => g.Id == groupId)
    .Select(g => new
    {
        /* ...some other fields are queried here... */
        ActiveLab = g.ActiveLabs.FirstOrDefault(al => al.LabId == labId)
    })
    .FirstAsync(cancellationToken);

приводит к этой ошибке:

MySqlException: You have an error in your SQL syntax; check the manual that corresponds to your
MySQL server version for the right syntax to use near
'(PARTITION BY `l`.`GroupId` ORDER BY `l`.`GroupId`, `l`.`LabId`) AS `row`'
at line 6

Проверка сгенерированного SQL выдает, что EF по какой-то причине вставляет PARTITION инструкция:

SELECT `g`.`Name`, `t0`.`GroupId`, `t0`.`LabId`, `t0`.`StartTime`
FROM `Groups` AS `g`
LEFT JOIN (
    SELECT `t`.`GroupId`, `t`.`LabId`, `t`.`StartTime`
    FROM (
        SELECT `l`.`GroupId`, `l`.`LabId`, `l`.`StartTime`, ROW_NUMBER() OVER(PARTITION BY `l`.`GroupId` ORDER BY `l`.`GroupId`, `l`.`LabId`) AS `row`
        FROM `ActiveLabs` AS `l`
        WHERE `l`.`LabId` = @__labId_1
    ) AS `t`
    WHERE `t`.`row` <= 1
) AS `t0` ON `g`.`Id` = `t0`.`GroupId`
WHERE `g`.`Id` = @__groupId_0
LIMIT 1

Я бы предпочел ожидать такой запрос:

SELECT `g`.`Name`, `l`.`GroupId`, `l`.`LabId`, `l`.`StartTime`
FROM `Groups` AS `g`
LEFT JOIN `ActiveLabs` AS `l`
ON `l`.`GroupId` = `g`.`Id`
WHERE `l`.`LabId` = @__labId_1 AND `g`.`Id` = @__groupId_0
LIMIT 1

Почему EF генерирует такой сложный запрос, когда простой JOIN on ActiveLabs будет достаточно?

Я тестирую с EF Core 3.1.2, Pomelo MySQL 3.1.1 и MySQL 5.7.14.


Моя база данных выглядит следующим образом: у меня есть две таблицы Groups

+----+--------+
| Id |  Name  |
+----+--------+
|  1 | Group1 |
|  2 | Group2 |
+----+--------+

и ActiveLabs

+---------+-------+----------------------------+
| GroupId | LabId |         StartTime          |
+---------+-------+----------------------------+
|       1 |     1 | 2020-03-01 00:00:00.000000 |
|       2 |     1 | 2020-03-01 00:00:00.000000 |
|       1 |     2 | 2020-03-08 00:00:00.000000 |
+---------+-------+----------------------------+

Последняя представляет отношение многие ко многим, которое отслеживает, какая лаборатория активен для какой группы. Таким образом, объект Group имеет свойство навигации ActiveLabs, которое указывает на активные лаборатории этой группы. Структура класса / таблицы и внешние ключи правильны и хорошо работают во всех случаях использования.


Редактировать: Похоже, PARTITION не поддерживается MySQL 5.7.14 вообще ( связанная проблема в репозитории Pitlo's GitHub). Обновление до MySQL 8.0 избавляет от сообщения об ошибке, теперь запрос работает; однако Я до сих пор не понимаю, почему EF генерирует оператор PARTITION (оконная функция) .

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