Ограничение возвращаемых объектов NHibernate

Я пытаюсь ограничить количество объектов, которые будут возвращать критерии NHibernate. Похоже, что стандарт использует SetMaxResults, но это не работает должным образом, если мои критерии включают ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ для отношения «многие ко многим».

Пример:

У собак есть хозяева (отношение «многие ко многим»), и мне нужно найти до 10 собак, которые принадлежат некоторой группе владельцев. Делает

session.CreateCriteria<Dog>()
  .CreateAlias("Owners", "Owners")
  .Add(Restrictions.In("Owners.Id", idCollection)
  .SetMaxResults(10)
  .List<Dog>();

преобразуется в SQL-запрос, например

SELECT TOP(10) * FROM DOGS d
  LEFT OUTER JOIN OWNERS_DOGS od ON d.id = od.id
  WHERE od.OWNER_ID IN (:valueone, :valuetwo)

Мое ограничение TOP применяется слишком рано, в результате чего собака с несколькими владельцами, которые соответствуют критериям, многократно подсчитывается до моего предела в 10. Есть ли чистый способ сообщить NHibernate, что я хочу, чтобы она увлажняла только первые X объектов dog? Я, вероятно, не смогу отказаться от выполнения полного SELECT в базе данных, но было бы неплохо, если бы я мог избежать загрузки каждой собаки в системе, поскольку я собираюсь отображать только 10 из них.


person iddqd    schedule 05.02.2013    source источник
comment
Но разве вы не ограничиваете owner_id? Значит, собаки с несколькими владельцами не должны быть проблемой (если вы не разрешаете дублирование строк в owner_dogs)?   -  person dotjoe    schedule 05.02.2013
comment
Спасибо что подметил это. Мой реальный сценарий немного сложнее. Я исправил пример, чтобы он был более применимым.   -  person iddqd    schedule 06.02.2013


Ответы (1)


Решение в этом случае - подзапрос. Нам нужно создать внутренний SELECT, который будет фильтроваться владельцами собак и возвращать ID собаки. Затем мы запросим Dogs и отфильтруем их по этому подзапросу. Наконец, наше разбиение на страницы будет правильным, пока оно выполняется над плоской структурой.

См. Этот ответ с более подробной информацией: https://stackoverflow.com/a/14080092/1679310

Подзапрос 15.8. Отдельные запросы и подзапросы:

DetachedCriteria subQuery = DetachedCriteria.For(typeof(Dog))
    // WHERE conditions go here
    .SetProjection( Projections.Property("ID") )
;

Запрос с правильным разбиением на страницы

session.CreateCriteria(typeof(Dog))
    .Add(Subqueries.PropertyEq("ID", subQuery));
    // PAGING goes here
    .SetMaxResults(10)
    .List();
person Radim Köhler    schedule 06.02.2013
comment
Ты классный парень! Спасибо за ответ. Единственное незначительное изменение, которое мне пришлось сделать, - это использовать Subqueries.PropertyIn (ID, subQuery) против PropertyEq, поскольку сам подзапрос возвращает несколько строк. - person iddqd; 06.02.2013
comment
отлично, если это работает;) Замечательно, что вы настроили его под свои нужды. удачи - person Radim Köhler; 06.02.2013