Установка fetchmode в NHibernate не устраняет проблему SELECT N + 1 - PullRequest
1 голос
/ 24 августа 2010

Я борюсь с чем-то довольно простым. У меня есть отношение один-ко-многим, и я устанавливаю режим fetch для внутреннего соединения в своем запросе Criteria. Я вижу, что полученный SQL включает в себя соединение, но он также лениво выбирает дочерние объекты. Что я делаю не так?

Отображения (в промышленности много производителей):

public class IndustryMap : ClassMap<Industry>
{
    public IndustryMap()
    {
        Id(industry => industry.ID);
        Map(industry => industry.Name);

        HasMany(x => x.Manufacturers)
            .KeyColumn("IndustryID")
            .AsSet()
            .Access.PascalCaseField(Prefix.Underscore)
            .LazyLoad();
    }
}

public class ManufacturerMap: ClassMap<Manufacturer>
{
      public ManufacturerMap()
      {
          Id(manufacturer=> manufacturer.ID);
          Map(manufacturer => manufacturer.Name);

          References(manufacturer => manufacturer.Industry, "IndustryID")
              .LazyLoad();
      }
}

Запрос:

var industries = this.Session.CreateCriteria<Industry>()
                                .CreateAlias("Manufacturers", "manu", JoinType.InnerJoin)
                                .AddOrder(new Order("Name", true))
                                .SetResultTransformer(new DistinctRootEntityResultTransformer())
                                .List<Industry>();

Результирующий SQL от NHProf (я бы ожидал, что оператор № 1 будет единственным оператором):

-- statement #1
SELECT   this_.Id           as Id5_1_,
         this_.LastUpdated  as LastUpda2_5_1_,
         this_.Name         as Name5_1_,
         manu1_.Id          as Id6_0_,
         manu1_.LastUpdated as LastUpda2_6_0_,
         manu1_.Name        as Name6_0_,
         manu1_.IndustryID  as IndustryID6_0_
FROM     Dealer.[Industry] this_
         inner join Dealer.[Manufacturer] manu1_
           on this_.Id = manu1_.IndustryID
ORDER BY this_.Name asc

-- statement #2
SELECT manufactur0_.IndustryID  as IndustryID1_,
       manufactur0_.Id          as Id1_,
       manufactur0_.Id          as Id6_0_,
       manufactur0_.LastUpdated as LastUpda2_6_0_,
       manufactur0_.Name        as Name6_0_,
       manufactur0_.IndustryID  as IndustryID6_0_
FROM   Dealer.[Manufacturer] manufactur0_
WHERE  manufactur0_.IndustryID = '529fde0e-dccf-456a-ab69-4a4b662aa0d2' /* @p0 */

-- statement #3
SELECT manufactur0_.IndustryID  as IndustryID1_,
       manufactur0_.Id          as Id1_,
       manufactur0_.Id          as Id6_0_,
       manufactur0_.LastUpdated as LastUpda2_6_0_,
       manufactur0_.Name        as Name6_0_,
       manufactur0_.IndustryID  as IndustryID6_0_
FROM   Dealer.[Manufacturer] manufactur0_
WHERE  manufactur0_.IndustryID = '529fde0e-dccf-456a-ab69-4a4b662aa0d3' /* @p0 */

-- statement #4
SELECT manufactur0_.IndustryID  as IndustryID1_,
       manufactur0_.Id          as Id1_,
       manufactur0_.Id          as Id6_0_,
       manufactur0_.LastUpdated as LastUpda2_6_0_,
       manufactur0_.Name        as Name6_0_,
       manufactur0_.IndustryID  as IndustryID6_0_
FROM   Dealer.[Manufacturer] manufactur0_
WHERE  manufactur0_.IndustryID = '529fde0e-dccf-456a-ab69-4a4b662aa053' /* @p0 */

-- statement #5
SELECT manufactur0_.IndustryID  as IndustryID1_,
       manufactur0_.Id          as Id1_,
       manufactur0_.Id          as Id6_0_,
       manufactur0_.LastUpdated as LastUpda2_6_0_,
       manufactur0_.Name        as Name6_0_,
       manufactur0_.IndustryID  as IndustryID6_0_
FROM   Dealer.[Manufacturer] manufactur0_
WHERE  manufactur0_.IndustryID = '529fde0e-dccf-456a-ab69-4a4b662aa245' /* @p0 */

1 Ответ

3 голосов
/ 24 августа 2010

Я воспроизвел ваш сценарий с небольшими изменениями, и результат, как и ожидалось.Проверьте следующее:

Классы домена:

public class Industry
{
    public virtual int ID { get; set; }
    public virtual string Name { get; set; }
    public virtual ICollection<Manufacturer> Manufacturers { get; set; }
}

public class Manufacturer
{
    public virtual int ID { get; set; }
    public virtual string Name { get; set; }
    public virtual Industry Industry { get; set; }
}

Отображение:

public class IndustryMap : ClassMap<Industry>
{
    public IndustryMap()
    {
        Id(industry => industry.ID);
        Map(industry => industry.Name);

        HasMany(x => x.Manufacturers)
            .KeyColumn("IndustryID")
            .AsSet()
            .Inverse()
            //.Access.PascalCaseField(Prefix.Underscore)
            .LazyLoad();
    }
}

public class ManufacturerMap : ClassMap<Manufacturer>
{
    public ManufacturerMap()
    {
        Id(manufacturer => manufacturer.ID);
        Map(manufacturer => manufacturer.Name);

        References(manufacturer => manufacturer.Industry, "IndustryID")
            .LazyLoad();
    }
}

Запрос:

var industries = session.CreateCriteria<Industry>()
                .SetFetchMode("Manufacturers", FetchMode.Eager) //this is it
                            .List<Industry>();

ОБНОВЛЕНИЕ:

Запрос заказа по производителям. Имя: * 10101

var industries = session.CreateCriteria<Industry>()                          
                    .SetFetchMode("Manufacturers", FetchMode.Eager) //this is it
                      .CreateAlias("Manufacturers","manu")
                      .AddOrder(Order.Asc("manu.Name")
                                .List<Industry>();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...