У меня есть объекты, подобные этим:Session.Get нагрузки с N + 1, даже если ленивым = ложь
public class User
{
public virtual int Id { get; set;}
public virtual Iesi.Collections.Generic.ISet<Character> Characters { get; set; }
}
public class Character
{
public virtual int Id { get; set;}
public virtual User User { get; set;}
public virtual Iesi.Collections.Generic.ISet<UserCharacterSmartChallengeTracker> SmartChallengeTrackers { get; set; }
}
public class UserCharacterSmartChallengeTracker
{
public virtual int Id { get; set; }
public virtual int? CharacterId { get; set; }
}
Они НЕ ленивы загружены.
Когда я session.Get<User>()
я вижу такие запросы:
SELECT smartchall0_.character_id as character3_1_,
smartchall0_.id as id1_,
smartchall0_.id as id51_0_,
smartchall0_.character_id as character3_51_0_,
FROM public.user_character_smart_challenge_trackers smartchall0_
WHERE smartchall0_.character_id = 48176 /* :p0 */
SELECT smartchall0_.character_id as character3_1_,
smartchall0_.id as id1_,
smartchall0_.id as id51_0_,
smartchall0_.character_id as character3_51_0_,
FROM public.user_character_smart_challenge_trackers smartchall0_
WHERE smartchall0_.character_id = 48175 /* :p0 */
-- and others
Я пытался поджать все из них в кэш сеанса:
var ids = session.Query<Character>().Where(x => x.User.Id == id)
.Select(x => x.Id)
.ToArray();
session.Query<UserCharacterSmartChallengeTracker>().Where(x => ids.Contains(x.Id)).ToArray();
с запросом
select character0_.id as col_0_0_
from public.characters character0_
where character0_.user_id = 9602 /* :p0 */
select usercharac0_.id as id51_,
usercharac0_.character_id as character3_5
from public.user_character_smart_challenge_trackers usercharac0_
where usercharac0_.id in (48176 /* :p0 */, 48175 /* :p1 */, 48174 /* :p2 */, 48173 /* :p3 */,
48172 /* :p4 */, 48171 /* :p5 */, 48170 /* :p6 */, 48169 /* :p7 */)
но NHibernate игнорирует тот факт, что все они уже загружены в кеш сеанса и генерируют то же самое N + 1 запросов! Как это исправить?
Update: поджимать с
session.QueryOver<Character>().Where(x => x.User.Id == id)
.Fetch(x => x.User).Lazy
.Fetch(x=>x.SmartChallengeTrackers).Eager
.List();
удаляет N + 1, но делает символы нагрузки NHibernate второй раз, когда я session.Get<User>
, который я хочу, чтобы избежать!
У вас была взглянуть на этот раздел в документации (http://nhibernate.info/doc/nh/en/index.html#performance-fetching-custom) ? –
Я понимаю, что предварительная загрузка не повлияет на запрос, который генерирует NH, только то, нужно ли полностью увлажнять объекты или просто получать их из кеша 1-го уровня. –
Вы действительно хотите использовать session.Get? почему бы не написать запрос, который проецирует на какой-либо объект, чтобы каждый раз не загружать весь граф объекта? –
Fran