Entity Framework генерирует проблему SQL (несколько объединений в одной таблице) - PullRequest
2 голосов
/ 30 июня 2011

Немного проблем с пониманием того, почему EF (4.1) генерирует определенный SQL-запрос. Здесь идет:

В основном у меня есть эти два класса

public class Rota
{
    public int RotaId { get; set; }

    public int RotaGroupId { get; set; }

    public virtual RotaGroup RotaGroup { get; set; }

    public int EmployeeId { get; set; }

    public virtual Employee Employee { get; set; }
    ...

и

public class RotaGroup
{
    public int RotaGroupId { get; private set; }

    public bool IsCurrentRota { get; set; }

    ...

Отображения для ротации следующие:

HasKey(r => r.RotaId);
Property(r=>r.RotaId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

HasRequired(r => r.RotaGroup).WithMany()
                             .HasForeignKey(r => r.RotaGroupId)
                             .WillCascadeOnDelete(false);

HasRequired(r => r.Employee).WithMany()
                            .HasForeignKey(r => r.EmployeeId)
                            .WillCascadeOnDelete(false);

...

Ok. Теперь следующий запрос linq:

_context.Rotas.Include(r => r.RotaGroup)
              .Where(r => r.EmployeeId == 1 && r.RotaGroup.IsCurrentRota)
              .ToList();

Создает следующий SQL:

SELECT ...columns...
FROM [dbo].[Rota] AS [Extent1]
INNER JOIN [dbo].[RotaGroup] AS [Extent2] ON [Extent1].[RotaGroupId] = [Extent2][RotaGroupId]
LEFT OUTER JOIN [dbo].[RotaGroup] AS [Extent3] ON [Extent1].[RotaGroupId] = [Extent3].[RotaGroupId] 
WHERE ([Extent2].[IsCurrentRota] = 1) AND ([Extent1].[MyIgluUserId] = 1

Я уверен, что вы видите проблему. Почему он присоединяется к rotaGroup (как следует), а затем выполняет левое внешнее объединение? Более того, столбцы из [Extent2] (внутреннее соединение) не используются. Используются только столбцы из левого внешнего бита соединения ([Extent3]).

Ответы [ 2 ]

4 голосов
/ 30 июня 2011

[Extent2] используется - это часть SQL WHERE. Результат запроса будет правильным, но производительность будет, вероятно, хуже. Я не думаю, что SQL-сервер оптимизирует это, чтобы избавиться от ненужного левого соединения.

Так EF генерирует запросы. Насколько я понимаю, EF не отслеживает использование наборов сущностей, поэтому эти две части запроса Include(r => r.RotaGroup) и Where(r => r.RotaGroup.IsCurrentRota) не связаны друг с другом. Левое соединение - результат Include, а внутреннее соединение - результат Where. Вы можете попытаться изменить запрос так, чтобы часть с Include была подзапросом фильтрации, но я сомневаюсь, что он будет работать по-другому.

1 голос
/ 28 октября 2011

Я столкнулся с аналогичной проблемой, когда несколько JOIN генерируются, когда они не нужны (то есть, запрос SQL можно легко изменить, включив в родительскую таблицу только один INNER JOIN вместо INNER и LEFT JOIN.к родительской таблице).

Моя проблема была также в проверке на равенство нескольких значений (например, где child.ParentID == 1 || child.ParentID == 2 || child.ParentID == 3), в результате чегопредложение (где tbl1 и tbl2 - объединенные таблицы INNER и LEFT, добавленные в оператор SELECT):

WHERE tbl1.ParentID = 1 или tbl2.ParentID IN (2, 3)

Оба изэти проблемы были исправлены в пакете ОСАГО за июнь 2011 года: ОС CTP - июнь 2011 года

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