Я знаю, что уже есть некоторые вопросы по этому поводу, большинство из которых касаются либо старых проблем, которые были решены, либо нескольких таблиц.Этот вопрос не рассматривается ни в одной из других проблем с «левым внешним соединением», которые я видел, я получаю INNER JOIN
и LEFT OUTER JOIN
для той же таблицы в том же запросе.
Схема таблицы:
Users: id (PK)
Name (VARCHAR)
ProfileImageUri (VARCHAR)
Locations: id (PK)
LocationBPNTips: id (PK)
TipText (VARCHAR)
CreatedAt (Datetime)
UserId (int) (FK to User.id, navigation property is called User)
LocationId (int) (FK to Location.id)
(есть еще, но это не важно :))
В моем сценарии я выполняю запрос к ссылочной таблице через проекцию и получаю дополнительное левое внешнее соединение,это то, что я запускаю ( прокомментированные части не имеют отношения к проблеме, закомментированы для более чистого SQL, EF выполняет сортировку правильно (даже лучше, чем я представлял :))):
LocationBPNTips
.Where(t => t.LocationId == 33)
//.OrderByDescending(t => intList.Contains(t.UserId))
//.ThenByDescending(t => t.CreatedAt)
.Select(tip => new LocationTipOutput
{
CreatedAt = tip.CreatedAt,
Text = tip.TipText,
LocationId = tip.LocationId,
OwnerName = tip.User.Name,
OwnerPhoto = tip.User.ProfileImageUri
}).ToList();
И это сгенерированный SQL
SELECT
[Extent1].[LocationId] AS [LocationId],
[Extent1].[CreatedAt] AS [CreatedAt],
[Extent1].[TipText] AS [TipText],
[Extent2].[Name] AS [Name],
[Extent3].[ProfileImageUri] AS [ProfileImageUri]
FROM [dbo].[LocationBPNTips] AS [Extent1]
INNER JOIN [dbo].[Users] AS [Extent2] ON [Extent1].[UserId] = [Extent2].[Id]
LEFT OUTER JOIN [dbo].[Users] AS [Extent3] ON [Extent1].[UserId] = [Extent3].[Id]
WHERE 33 = [Extent1].[LocationId]
Как видите, LEFT OUTER JOIN
делается на той же таблице INNER JOIN
Я думаю, что оптимальный кодбыть (обратите внимание, я переименовал Extent3 в Extent2 вручную и добавил комментарий. это не было сгенерировано EF !!) - с моими текущими данными, это работает примерно на 22% быстрее (при сортировке этот% должен быть выше без сортировки), поскольку нет необходимости в дополнительном соединении ..
SELECT
[Extent1].[LocationId] AS [LocationId],
[Extent1].[CreatedAt] AS [CreatedAt],
[Extent1].[TipText] AS [TipText],
[Extent2].[Name] AS [Name],
[Extent2].[ProfileImageUri] AS [ProfileImageUri]
FROM [dbo].[LocationBPNTips] AS [Extent1]
INNER JOIN [dbo].[Users] AS [Extent2] ON [Extent1].[UserId] = [Extent2].[Id]
--LEFT OUTER JOIN [dbo].[Users] AS [Extent3] ON [Extent1].[UserId] = [Extent3].[Id]
WHERE 33 = [Extent1].[LocationId]
РазличныеЗапросы, которые я пробовал (проекция относится к анонимному типу):
LocationBPNTips
.Where(t => t.LocationId == 33)
//.OrderByDescending(t => intList.Contains(t.UserId))
//.ThenByDescending(t => t.CreatedAt)
.Select(tip => new
{
CreatedAt = tip.CreatedAt,
Text = tip.TipText,
LocationId = tip.LocationId,
OwnerName = tip.User,
OwnerPhoto = tip.User
}).ToList()
Вывод SQL был испорчен, он дважды выбирал всю пользовательскую таблицу в том же формате, что и выше, внутренний, затем левый внешний.Я думаю, что теоретически я могу понять, почему это происходит для этого случая, потому что я дважды запрашивал данные - хотя это могло быть сделано в памяти, а не с помощью SQL с дополнительным объединением - но в моем случае я не просилДанные дважды я запрашивал для разных столбцов только один раз.Я выполнил этот тест, чтобы убедиться в совместимости двойного соединения.
Я также попытался запустить:
LocationBPNTips
.Where(t => t.LocationId == 33)
.Select(tip => new
{
CreatedAt = tip.CreatedAt,
Text = tip.TipText,
LocationId = tip.LocationId,
OwnerName = tip.User.Name
}).ToList()
Этот тест вернул чистое единственное внутреннее соединение, как и ожидалось, но это не то, что яя пытаюсь сделать
Так что вопрос : это ошибка?я неправильно использую EF?