Критерии подкачки NHibernate с нетерпением fetchmode.(используя беглый NH) - PullRequest
0 голосов
/ 02 декабря 2010

Вопрос: Как получить загруженные критерии, чтобы возвращать постраничные результаты для корневого объекта со всеми установленными дочерними коллекциями fetchmode = eager.

Я пытаюсь получить постраничный набор результатов из 10 элементов с загруженными дочерними коллекциями. Проблема в том, что запрос выбирает топ-10, обернутый вокруг всего выбора. Причины, по которым он возвращает только первые 10 результатов, включая все объединенные записи. Если первая сущность имеет 10 дочерних объектов, то мой набор результатов вернет 1 сущность с 10 загруженными дочерними объектами. Мне нужно, чтобы сущности и дочерние коллекции возвращались гидратированными (ленивый). Если я отключаю ленивую загрузку и запускаю этот запрос, я получаю n + 1 запрос для каждого сотрудника в наборе результатов.

Это мой основной процесс запроса:

criteria = context.Session.CreateCriteria<Associate>();
criteria.SetMaxResults(10); //hardcoded for testing
criteria.SetFirstResult(1); //hardcoded for testing
criteria.SetFetchMode("Roles", NHibernate.FetchMode.Eager);
criteria.SetFetchMode("Messages", NHibernate.FetchMode.Eager);
criteria.SetFetchMode("DirectReports", NHibernate.FetchMode.Eager);
criteria.SetResultTransformer(new DistinctRootEntityResultTransformer());
return criteria.List<Associate>();


public AssociateMap()
    {
        ReadOnly();
        Id(x => x.AssociateId);
        Map(x => x.FirstName);
        Map(x => x.LastName);
        Map(x => x.ManagerId);
        Map(x => x.Department);
        Map(x => x.Email);
        Map(x => x.JobTitle);

        Map(x => x.LastFirstName).Formula("LTRIM(RTRIM(LastName)) + ', ' + LTRIM(RTRIM(FirstName))");

        HasMany(x => x.Messages).KeyColumn("AssociateId").Inverse().Cascade.All();
        HasMany(x => x.Roles).Element("RoleKey");
        HasMany(x => x.DirectReports).KeyColumn("ManagerId").Cascade.None().ForeignKeyConstraintName("FK_Associate_Manager");
        //HasMany(x => x.DirectReports).Element("ManagerId").CollectionType(typeof(Domain.Associate));


    }

1 Ответ

3 голосов
/ 04 декабря 2010

В результате решение использовало подзапрос, чтобы установить максимальные результаты. Я добавил подзапрос, используя Subqueries.PropertyIn. Я клонирую "критерии" в "ограничитель", потому что я добавил выражение критерия в коде, который не показан. Поэтому мне нужно клонировать эти критерии в подзапросе, чтобы 10 лучших вариантов были в выражении «IN». Теперь я могу загрузить дочерние коллекции и добавить нумерацию страниц к корневому объекту, чтобы получить 10 энтов без проблем с декартовой или n + 1. Я постараюсь получить более полный и организованный код.

//criteria = context.Session.CreateCriteria<Associate>(); 
//changed criteria to DetachedCriteria.
criteria = DetachedCriteria.For<Associate>();

DetachedCriteria limiter = CriteriaTransformer.Clone(criteria); 
limiter.SetProjection(Projections.Id());
limiter.SetMaxResults(10);
criteria.Add(Subqueries.PropertyIn("AssociateId", limiter));

criteria.SetFetchMode("Roles", NHibernate.FetchMode.Eager); 
criteria.SetFetchMode("Messages", NHibernate.FetchMode.Eager); 
criteria.SetFetchMode("DirectReports", NHibernate.FetchMode.Eager); 
criteria.SetResultTransformer(new DistinctRootEntityResultTransformer()); 
return criteria.List<Associate>(); 
...