Оптимизация сгенерированного SQL NHibernate - PullRequest
2 голосов
/ 12 марта 2012

У меня есть запрос NHibernate LINQ, подобный этому:

var maxNumber = session
    .Linq<Child>()
    .Where(c => c.Parent == parent)
    .Max(c => c.Number);

NHibernate генерирует следующий SQL:

SELECT max(this_.Number) 
FROM [Child] as this_
LEFT OUTER JOIN [Parent] parent1_
ON this_.Parent_id = parent1_.Id
WHERE parent1_.Id = @p0

Я бы хотел, чтобы он просто генерировал что-то вроде:

SELECT max(this_.Number) 
FROM [Child] as this_
WHERE this_.Parent_id = @p0

Я бы ожидал, что планы выполнения будут одинаковыми для обоих запросов, но это не так.

Мои сущности определены так:

class Parent
{
    long Id { get; set; }
    string Name { get; set; }
}

class Child
{
    long Id { get; set; }
    int Number { get; set; }
    Parent Parent { get; set; } // mapped as FK
}

С отображением, подобным этому:

class ParentMap : ClassMap<Parent>
{
    public ParentMap()
    {
        Id(x => x.Id).GeneratedBy.Increment();
        Map(x => x.Name);
    }
}

class ChildMap : ClassMap<Child>
{
    public ChildMap()
    {
        Id(x => x.Id).GeneratedBy.Increment();
        Map(x => x.Number);
        References(x => x.Parent);
    }
}

Как я мог переписать его, чтобы получить последний вывод, используя NHibernate? Это делается внутри метода репозитория, поэтому я могу легко переключиться на HQL или что-то еще, если это необходимо (или, конечно, просто DbCommand, если все остальное не работает).

Я использую NHibernate 2.0 с LINQ-to-NHibernate и SQL Server 2008 R2.

Ответы [ 2 ]

3 голосов
/ 12 марта 2012

Когда я создаю запрос и явно указываю, Id - это свойство, к которому я хочу запросить, а не сущность, которую я получаю «оптимизированным» запросом. i.e.:

session
    .Query<Child>()
    .Where(c => c.Parent.Id = parent.Id)
    .Max(c = c.Number);
2 голосов
/ 12 марта 2012

Если вы используете Query<>, вы не можете использовать NHibernate 2.0.

Если предположить, что это опечатка, а вы имели в виду 3.0, попробуйте обновить до 3.2.Я только что проверил, что ваш запрос работает точно так, как ожидалось.

Теперь - это ошибка в 3.2, которая вызывает дополнительное объединение, если вы напишите свой запрос следующим образом:

var maxNumber = session
    .Query<Child>()
    .Where(c => c.Parent.Id == parent.Id)
    .Max(c => c.Number);

... И это исправлено в 3.3 (предварительная версия вышла со вчерашнего дня)

...