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) в зависимости от размера пакета и размера страницы.