2014-01-11 4 views
0

У меня есть код, вызывающий список групп, которые имеют отношение друг к другу с пользователями через таблицу с именем GroupToUsers.Fluent NHibernate не возвращает отдельные значения

Я пытаюсь перечислить список групп, содержащий список пользователей в каждой группе.

Я новичок в NHibernate, поэтому, пожалуйста, будьте терпеливы :).

Код:

IQueryOver<Group, Group> query = this.Session.QueryOver<Group>() 
    .Where(g => g.IsActive && !g.IsDeleted) 
    .Fetch(g => g.Users).Eager 
    .JoinAlias(g => g.Users,() => groupToUser, JoinType.LeftOuterJoin) 
    .Where(g => g.Owner.Id == userId || (groupToUser.Group != null && groupToUser.IsAccepted && groupToUser.Profile.Id == userId)) 
    .OrderBy(g => g.Description).Asc 
    .TransformUsing(Transformers.DistinctRootEntity); 
     IQueryOver<Group> countQuery = query.ToRowCountQuery().Cacheable(); 
     IFutureValue<int> totalCount = countQuery.FutureValue<int>(); 

     result.Items = query.Take(size + 1).Skip((page - 1) * size).List(); 
     result.Count = totalCount.Value; 

Я ожидал 9 записей, но это возвращает счетчик 11 (который есть 11 строк 2 группы, повторяющимися дважды, поскольку каждый из них имеет 2 пользователей каждый)

Так что мой вопрос в том, почему это результат.Count возвращает 11 count вместо 9?

+0

Если вы новичок в NHibernate, был использован [tag: queryover], а не [tag: linq-to-nhibernate] преднамеренный выбор? Многие новички идут с QueryOver, полагая, что это «linq» NHibernate из-за использования лямбда, но нет, это что-то еще. –

ответ

1

У вас есть смысл сказать, что счетчик увеличивается с каждой пользовательской записью в коллекции Users. Это результат вызова .Fetch().

Существует два запроса. Первый (оригинал с преобразованием), а второй - просто звонок, чтобы получить счет. Проблема заключается в том, что второй запрос не вызывает

.TransformUsing(Transformers.DistinctRootEntity); 

(как первый делает). Это всего лишь клон предыдущего запроса (без заказа) и поэтому он возвращает реальный 11.

В целом. Я бы предложил, не используйте выборку по сопоставленным коллекциям. Это имеет эти побочные эффекты ... например. непредсказуемые пейджинговой (Take() и Skip() будет применяться на стороне БД, в то время как Distinct корень на/сервере приложений клиента)

Каков путь, я бы предпочел, и использовать длительное время, является использование пакетный выбор. Это означает, что изменить отображение, как описано здесь: 19.1.5. Using batch fetching

Использование Fluent отображения вы должны обновить отображение пользователей, как этого

HasMany(x => x.Users) 
    ... 
    .BatchSize(25); 

И будет выполнен по меньшей мере два запроса (возможно 3) .. один для корневого объекта, один для элементов коллекции (пользователей) .. но не для каждого корневого элемента, а как пакет. Итак, не все в один раз, но все еще очень эффективно

Смежные вопросы