2012-03-12 2 views
2

У меня есть запрос NHibernate LINQ, как это:Оптимизация NHibernate генерируется SQL

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.

+0

Использование NH 3.2 Я получил оптимизированный запрос. Я предполагаю, что 2.0 просто не так умен в построении запроса. И из-за этого я не уверен, что HQL решит его. –

ответ

3

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

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

Хм, я пробовал это, и я уверен, что дал мне тот же результат, но я, возможно, сделал что-то неправильно, я сейчас проверю его. (edit :) Нет, похоже, что это не работает. Возможно, это версия NH, как упоминается @JayOtterbein? – Groo

+0

Наконец-то я решил переключиться на NH 3.2. Поставщик LINQ в NH2 постоянно искажался. – Groo

2

Если вы используете 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 (версия пре-релиз вне вчера)

+0

Это NH2, но я забыл упомянуть, что я использую LINQ2NHibernate, который был объединен с NH в v3 IIRC. – Groo

+1

Доступ к старому провайдеру LINQ осуществляется с помощью 'session.Linq <>', а не 'session.Query <>'. Поставщик в NH 3 был написан с нуля, совершенно не связан со старым и работает в самых разумных случаях. Я предлагаю вам обновить. –

+0

Хорошо, ** что ** была опечаткой. :) Nevermind, я взломал 'DBCommand' вручную внутри моего метода репозитория, так как он короткий, и это относительно старый проект, поэтому я хотел избежать обновления в это время. – Groo

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