Критерий API с предложением в отношении многих ко многим

В NHibernate 3 введено предложение With для Criteria API. Я пытаюсь использовать его, чтобы ограничить объединение отношений "многие ко многим", и NHibernate применяет дополнительное ограничение объединения к таблице ссылок, а не к правильной таблице.

У меня есть отношения многие ко многим между Player и Address, и я хочу вернуть Player и его почтовый адрес, ограничив Address.IsMailingAddress. Ограничение IsMailingAddress в предложении where не возвращает записи, которые не имеют почтового адреса (или вообще не имеют адреса), поэтому мне нужно ограничить его в соединении. Приведенный ниже код упрощен, и я не могу использовать HQL.

Запрос:

var target = session.CreateCriteria<Player>()
    .SetProjection(Projections.Property("PlayerId"))
    .CreateAlias("Addresses", "ad", JoinType.LeftOuterJoin, Restrictions.Eq("ad.IsMailingAddress", true))
    .Add(Restrictions.Eq("LastName", "Anonymous"))
   .List();

генерирует SQL:

SELECT this_.PlayerId as y0_
FROM   dbo.VPlayerExisting this_
       left outer join dbo.LinkPlayAddr addresses3_
         on this_.PlayerId = addresses3_.PlayerId
            and (ad1_.MailingAddressFlag = 1 /* @p0 */)
       left outer join dbo.VAddress ad1_
         on addresses3_.AddressId = ad1_.AddressId
            and (ad1_.MailingAddressFlag = 'Anonymous' /* @p1 */)
WHERE  this_.Name_Last = @p2

MailingAddressFlag (столбец, сопоставленный с IsMailingAddress) ограничен в таблице ссылок "многие ко многим", где он не существует, и ограничение LastName применяется при объединении с таблицей адресов. Запрос действительно выполняется, но, конечно, сервер базы данных вызывает исключение.

Это ошибка, не поддерживается или я делаю это неправильно?

2 ответа

var target = session.CreateCriteria<Player>()
    .CreateAlias("Addresses", "ad", JoinType.InnerJoin)
    .Add(Restrictions.Eq("LastName", "Anonymous"))
    .Add(Restrictions.Eq("ad.IsMailingAddress",true))
    .List();

Просто внутреннее присоединение к почтовому адресу с ограничением на IsMailingAddress?

Должны вернуть игроков (где LastName является "Анонимным") с их MailingAddress, где у них есть адрес, и этот адрес помечен как IsMailingAddress.

Решение ниже. Должен быть только один адрес с установленным параметром IsMailingAddress, поэтому условие или позволяет соединению быть успешным, если есть один или ни один, использующий внутреннее соединение.

var target = session.CreateCriteria<Player>()
    .SetProjection(Projections.Property("PlayerId"))
    .CreateAlias("Addresses", "ad", JoinType.InnerJoin)
    .Add(RestrictionsOr(Restrictions.Eq("ad.IsMailingAddress", true), Restrictions.IsNull("ad.AddressId")))
    .Add(Restrictions.Eq("LastName", "Anonymous"))
   .List();
Другие вопросы по тегам