NHibernate QueryOver с Fetch, результатом которого является несколько SQL запросов и дБ

Я пытаюсь выбрать объект и получить связанный список:

    Session.QueryOver<UserRole>()
           .Fetch(x => x.UsersInRole).Eager
           .List();

Что приводит к большому количеству обращений к базе данных. Первый что-то вроде:

 SELECT ... FROM UserRoles
 left outer join UsersInRoles on ...

И еще сотни отдельных запросов, которые выглядят примерно так:

 SELECT ... FROM UsersInRoles
 left outer join UserRoles on ...
 WHERE UserRoles.UserId=?

Отображение выглядит следующим образом:

public class UserRoleMap : ClassMap<UserRole>
{
    public UserRoleMap()
    {
        Id(x => x.Id);
        Map(x => x.RoleName);
        HasManyToMany(x => x.UsersInRole)
        .Inverse()
        .LazyLoad()
        .Table("UsersInRoles");
    }
}

1 ответ

Решение

Я бы сказал, что такого поведения мы должны ожидать. Давайте рассмотрим сценарий, в котором у нас в системе 2 пользователя и 2 роли

User1 - Role1 // has only Role1
User2 - Role1 // now we see that Role2 has more then User1
User2 - Role2

Допустим, что первый запрос будет получать только User1 и его отношение "многие ко многим" Role1. Что мы имеем в ISession на данный момент это только User1, поэтому набор Users для Role1 является неполным (мы не можем повторно использовать объекты, загруженные в ISession в данный момент). Но как узнать, где мы? Что все данные загружены для Role1 есть или нет в сессии?

Новый запрос, загружающий данные для Role1 должен быть выдан. И таким образом, мы можем в конце концов получить десятки этих запросов...

То, что я считаю лучшим решением (я использую его почти во всех сценариях), это batch-size настройка: 19.1.5. Использование пакетной выборки

HasManyToMany(x => x.UsersInRole)
  ...
  .BatchSize(25)

Отметьте все карты своей коллекции с помощью .BatchSize(25) и сделать это даже для карты классов. Это приведет к более чем 1 сценарию SQL, но в конце не более 1 + (2-4) в зависимости от размера пакета и размера страницы.

Другие вопросы по тегам