Как «перевести» SQL за исключением (H) Hibernate (Criteria API)? - PullRequest
2 голосов
/ 30 марта 2012

Я работаю над делом, где у меня обычно в SQL должно быть ключевое слово «кроме».В данный момент я не нашел решения для этого в NHibernate.

Это решение, в котором у вас есть две таблицы: таблица пользователей и таблица FK (включая PK для простой работы в NH).Смысл SQL ниже состоит в том, чтобы предоставить все записи для пользователей, которые еще не помечены определенным пользователем.Так что, если у нас есть 3 пользователя: Джон, Джейн и Джелайн.Если Джон никого не пометил: верните Джейн и Джелена. Если Джон пометил Джейн: верните Джелена. Если Джон пометил и Джейн, и Джелена: ничего не верните.

SQL, чтобы получить пользователей, которые еще не помечены:

SELECT Id, DisplayName, Date, ProfilePicUrl
FROM MyDB.dbo.Users u
EXCEPT
SELECT u.Id, Displayname, Date, ProfilePicUrl
FROM MyDB.dbo.Users u
FULL OUTER JOIN MyDB.dbo.TaggedUsers t
ON u.Id=t.TargetId
WHERE
t.ShooterId = '1234' OR
u.Id = '1234'

Ответы [ 3 ]

2 голосов
/ 30 марта 2012

Я думаю, в ICritearia нет ИСКЛЮЧЕНИЯ, но вы можете использовать "Not IN":

session.QueryOver(T).WhereRestrictionOn(t => t.SomeProperty).Not.IsIn(object[])

Я думаю, что это то же самое, посмотрите:

1 голос
/ 30 марта 2012

Что ж, я думаю, вы можете перевести свое утверждение в утверждение, используя внешние объединения:

select id, DisplayName, Date, ProfilePicUrl
from MyDB.dbo.Users u 
right outer join MyDB.dbo.TaggedUsers t on u.id = t.targetId
where t.ShooterId = '1234' or u.ID <> '1234' and t.ShooterId is null

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

.CreateAlias("TaggedUsers", "t", NHibernate.SqlCommand.JoinType.LeftOuterJoin)
.Add(Restrictions.IsNull("t.ShooterId")
.Add(Restrictions.Not(Restrictions.Eq("ID));

Всегда сложно создать это без тестирования - но я надеюсь, что вы поняли мою идею.

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

хорошо - похоже, это должно бытьлевое внешнее соединение - не правое внешнее соединение

0 голосов
/ 02 апреля 2012

Я проверял два ответа Антона и Бернхардруша и попробовал.

При чтении одного ответа я подумал, что можно переписать мой запрос с помощью внешнего левого соединения и отфильтровать записи с использованием NOT IN.

Это привело меня к этому коду:

SELECT *
FROM MyDB.dbo.Users u 
LEFT OUTER JOIN MyDB.dbo.TaggedUsers t ON u.Id=t.TargetId
WHERE t.ShooterId <> '6A17DC45-AB54-4534-B13B-A02001347664' 
  AND u.Id <> '6A17DC45-AB54-4534-B13B-A02001347664'
   OR t.ShooterId is null

Переведено с помощью Criteria API, но, к сожалению, этот код не работает при использовании нескольких пользователей .

В этот момент Я решил работать с кодом вместо SQL .

Таким образом, я сделаю два запроса (выберите всех пользователей и выберите всех помеченных пользователей, соответствующих идентификатору пользователя) с прикрепленным к нему .future и отфильтруйте первый с последним.

Если кто-то знает лучшее решение. Пожалуйста, дайте мне знать.

Возможно, если не поступить в NHibernate позже. Посмотрим. Сейчас я отвечу на этот вопрос своим собственным ответом.

...