NHibernate / QueryOver: как оставить соединение с параметром

1

Есть ли способ в NHibernate/QueryOver API передать параметр уже в сопоставлении (поэтому он использует параметр как фиксированное значение для всех запросов в этом конкретном экземпляре).

Мне нужно это (или обходное решение), потому что у меня есть такое же представление в базе данных:

CREATE VIEW ProblematicView
AS
SELECT
    v.*,
-- lots of data
FROM someView v
LEFT JOIN someTable t ON v.ForeignKey = t.ForeignKey

Теперь дополнительно к матчу ForeignKey мне нужна дополнительная проверка для такого свойства:

AND t.SomeOtherValue = @myParameter

что невозможно, поскольку нет возможности напрямую передавать параметры в представление. С помощью функции, связанной с таблицей, это было бы возможно, но тогда я не знаю, как ее сопоставить с NHibernate/QueryOver.

Также функциональный подход будет трудно реализовать, поскольку огромный параметр QueryOver используется для фильтрации всех остальных свойств (поскольку представление используется для поиска бизнес-объектов)

В настоящее время я применяю фильтр SomeOtherValue/@myParameter для всего представления как часть моего QueryOver.

Это моя главная проблема:

Использование, например:

SELECT
    v.*,
-- lots of data
FROM someView v
LEFT JOIN someTable t ON v.ForeignKey = t.ForeignKey AND t.SomeOtherValue = 123
 (followed by alot of other property checks...)

вернет другой результат (NULL-записи для t.SomeOtherValue, включенные в намерение из-за левого соединения)

чем использование:

SELECT * FROM ProblematicView where SomeOtherValue = 123
 (followed by alot of other property checks)

Поскольку теперь левое соединение происходит внутри представления, не проверяя SomeOtherValue, и, поскольку проверка SomeOthervalue применяется независимо от левого соединения, все значения NULL будут исключены (что является неправильной бизнес-логикой).

Также использование:

SELECT * FROM ProblematicView where SomeOtherValue = 123 OR SomeOtherValue = NULL
 (followed by alot of other property checks)

похоже, не помогает, поскольку значения NULL по-прежнему игнорируются...

Поэтому единственным способом, который я могу себе представить, чтобы решить эту проблему, было бы найти способ передать свойство SomeOtherValue каким-либо образом в представление, чтобы он мог использовать его как параметр в самом представлении (а не в предложении where) или, может быть, каким-то образом используйте функцию таблицы на основе sql с параметром для модели...

РЕДАКТИРОВАТЬ:

После еще нескольких исследований мне удалось, надеюсь, упростить проблему:

Я пытаюсь преобразовать этот SQL:

Select v.*, ... from (someView v LEFT JOIN someTable t ON v.ForeignKey = t.ForeignKey) 
WHERE SomeOtherValue = 123

(где SomeOtherValue исходит от некоторой другой таблицы)

к этому:

Select v.*, ... from someView v LEFT JOIN someTable t on v.ForeignKey = t.ForeignKey
AND t.SomeOtherValue = 123

используя NHibernate/QueryOver. Обратите внимание, что во второй версии свойство SomeOthervalue проверяется непосредственно в левом соединении, где в первой версии оно неправильно применяется только после левого соединения.

Мне нужно найти способ написать последний оператор SQL таким образом, чтобы я мог помещать его внутри представления, все еще имея возможность передавать 123 в качестве параметра SomeOtherValue.

Теги:
nhibernate
queryover

1 ответ

2

Вы можете добавить условие к предложению join, используя перегрузку JoinQueryOver или JoinAlias которая принимает параметр withClause. Например:

SomeTable stAlias = null;

session.QueryOver<ProblematicView>()
    .Left.JoinAlias(
        pv => pv.SomeTable,              // Join path
        () => stAlias,                   // alias assignment
        st => st.SomeOtherValue == 123)  // "with" clause
    /* etc. */

"С" частью объединения QueryOver является то, что добавит условие к left outer join в SQL. Вышеупомянутое должно генерировать это:

SELECT /* select list */
FROM   [ProblematicView] this_
       left outer join [SomeTable] sometable1_
         on this_.Id = sometable1_.ProblematicViewId
            and (sometable1.SomeOtherValue = 123 /* @p0 */)

Если я правильно понимаю, это должно помочь решить вашу проблему.

Несколько замечаний о добавлении предложения "with":

  • Интересно, что все перегрузки JoinQueryOver и JoinAlias которые позволяют вам указывать предложение "с", требуют, чтобы вы назначали псевдоним, когда выполняете соединение.
  • Вы не можете (насколько я знаю), генерировать SQL с or в состоянии присоединиться. предложение "с" всегда and равно отображается с условием сопоставленного соединения (т.е. FK → PK)
  • 0
    Спасибо за ваш ответ! Ваше решение выглядит очень близко к тому, что мне нужно. Однако я не уверен, как отобразить свойство SomeTable в моей модели основного вида (для пути соединения). ProblematicView не имеет никакого отношения к SomeTable (кроме внешнего объединения) ни в представлении sql, ни в модели NHibernate.
  • 0
    @Philipp: Извините, я пропустил это - да, это требует наличия отношений между ними. К сожалению, QueryOver / Criteria / HQL будет работать только с сопоставленными отношениями. Насколько сложно было бы отобразить ваше представление и связь между представлением и SomeTable ?
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню