NHibernate создает SQL с плохим соединением - PullRequest
7 голосов
/ 17 февраля 2012

У меня есть запрос NHibernate Linq, который не работает так, как я ожидал.

Проблема, похоже, связана с использованием пустого столбца int в левой объединенной таблице в предложении where. Это заставляет объединение действовать как внутреннее объединение.

var list = this.WorkflowDiaryManager.WorkflowActionRepository.All
    .Fetch(x => x.CaseView)
    .Fetch(x => x.WorkflowActionType)
    .ThenFetchMany(x => x.WorkflowActionPriorityList)
    .Where(x => x.AssignedUser.Id == userId || x.CaseView.MooseUserId == userId)

SQL, созданный этим, выглядит следующим образом (начиная с объединения - вам не нужно видеть все выборки)

from Kctc.WorkflowAction workflowac0_ 
left outer join Kctc.WorkflowCaseView workflowca1_ on workflowac0_.CaseId=workflowca1_.CaseId 
left outer join Kctc.WorkflowActionType workflowac2_ on workflowac0_.WorkflowActionTypeId=workflowac2_.WorkflowActionTypeId 
left outer join Kctc.WorkflowActionPriority workflowac3_ on workflowac2_.WorkflowActionTypeId=workflowac3_.WorkflowActionTypeId
,Kctc.WorkflowCaseView workflowca4_ 
where workflowac0_.CaseId=workflowca4_.CaseId 
and (workflowac0_.AssignedUser=@p0 or workflowca4_.[MooseUserId]=@p1);
@p0 = 1087 [Type: Int32 (0)],
@p1 = 1087 [Type: Int32 (0)]

Таким образом, часть, которая вызывает проблему, это строка 5 фрагмента выше. Как вы можете видеть, NHibernate пытается сделать соединение старой школы в моем представлении WorkflowCaseView. Это заставляет запрос исключать действительные действия, которые не имеют CaseId в таблице WorkflowAction.

Может ли кто-нибудь объяснить, почему NHibernate пишет этот SQL, и как я могу побудить его создать лучший запрос?

Спасибо!

Важные биты из WorkflowActionMap

        Table("Kctc.WorkflowAction");
        Id(x => x.Id).GeneratedBy.Identity().Column("WorkflowActionId");
        References(x => x.WorkflowActionType).Column("WorkflowActionTypeId").Unique();
        References(x => x.CompletedBy).Column("CompletedBy");
        References(x => x.CaseView).Column("CaseId").Not.Update().Unique();
        References(x => x.AssignedUser).Column("AssignedUser");

Важные биты из WorkflowCaseViewMap

        Table("Kctc.WorkflowCaseView");
        Id(x => x.Id).Column("CaseId");
        Map(x => x.MooseUserId).Nullable();

Глядя на это, мне интересно, должен ли я иметь HasMany, возвращающуюся в другую сторону ...

EDIT. Кажется, не помогает

Ответы [ 3 ]

3 голосов
/ 17 февраля 2012

Я думаю, вам нужно изменить предложение Where на следующее:

.Where(x => x.AssignedUser.Id == userId || 
       (x.CaseView != null && x.CaseView.MooseUserId == userId))

С вашим текущим предложением Where вы сообщаете NHibernate, что всегда будет CaseView, потому что вы безоговорочно получаете доступ к его свойствам. Основываясь на этой информации, NHibernate оптимизирует ваш запрос с left outer join до inner join (что такое объединение "старой школы")

0 голосов
/ 29 февраля 2012

Попробуйте использовать Fluent NHibernate.Что-то вроде следующего должно привести вас в правильное состояние:

var List<WorkflowAction> = FluentSessionManager.GetSession().CreateCriteria<WorkflowAction>()
        .SetFetchMode("CaseView", FetchMode.Eager)
        .SetFetchMode("WorkflowActionType", FetchMode.Eager)
        .SetFetchMode("WorkflowActionPriorityList", FetchMode.Eager)
        .CreateAlias("AssignedUser", "au")
        .CreateAlias("CaseView", "cv")
        .Add(Expression.Or(Expression.Eq("au.Id", userId),  Expression.Eq("cv.MooseUserId", userId)))
        .List<WorkflowAction>();

Имейте в виду, у меня есть специальный класс, который расширяет FluentSessionManager.GetSession (), где я могу вызвать его напрямую с помощью простого вспомогательного классана постраничной основе.Ваши настройки FluentSessionManager могут значительно отличаться.Но в конечном итоге в «.CreateCriteria () ...» ваш код и мой должны совпадать.Предполагая, что «WorkflowAction» - это таблица, к которой вызывается запрос.

0 голосов
/ 27 февраля 2012

Я реализовал это соединение, используя хранимую процедуру.Надеюсь, NHibernate скоро исправит эту ошибку.

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