0

У меня есть объекты, подобные этим: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>, который я хочу, чтобы избежать!

+0

У вас была взглянуть на этот раздел в документации (http://nhibernate.info/doc/nh/en/index.html#performance-fetching-custom) ? –

+0

Я понимаю, что предварительная загрузка не повлияет на запрос, который генерирует NH, только то, нужно ли полностью увлажнять объекты или просто получать их из кеша 1-го уровня. –

+0

Вы действительно хотите использовать session.Get ? почему бы не написать запрос, который проецирует на какой-либо объект, чтобы каждый раз не загружать весь граф объекта? – Fran

ответ

0

Я использовал фьючерсы:

 var q = session.Query<User>().Where(x => x.Id == id); 

     var lst = new List<IEnumerable> 
     { 
      q.FetchMany(x => x.Characters).ToFuture(), 
      q.Fetch(x=>x.UpdateableData).ToFuture(), 
      session.QueryOver<User>().Where(x => x.Id == id) 
       .Fetch(x=>x.Characters).Eager 
       .Fetch(x => x.Characters.First().SmartChallengeTrackers).Eager 
       .Future() 
     }; 

     var r = session.QueryOver<User>().Where(x => x.Id == id) 
      .TransformUsing(Transformers.DistinctRootEntity) 
      .Future(); 

     foreach (IEnumerable el in lst) 
     { 
      foreach (object o in el) 
      { 

      } 
     } 

     return r.ToArray(); 

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

  • Нет связанных вопросов^_^