C# 优化NHibernate生成的SQL

C# 优化NHibernate生成的SQL,c#,sql,sql-server,nhibernate,linq-to-nhibernate,C#,Sql,Sql Server,Nhibernate,Linq To Nhibernate,我有一个NHibernate LINQ查询,如下所示: var maxNumber = session .Linq<Child>() .Where(c => c.Parent == parent) .Max(c => c.Number); class Parent { long Id { get; set; } string Name { get; set; } } class Child { long Id { get

我有一个NHibernate LINQ查询,如下所示:

var maxNumber = session
    .Linq<Child>()
    .Where(c => c.Parent == parent)
    .Max(c => c.Number);
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);
    }
}
var maxNumber = session
    .Query<Child>()
    .Where(c => c.Parent.Id == parent.Id)
    .Max(c => c.Number);
我希望它只生成如下内容:

SELECT max(this_.Number) 
FROM [Child] as this_
WHERE this_.Parent_id = @p0
我本以为这两个查询的执行计划会完全相同,但事实并非如此

我的实体定义如下:

var maxNumber = session
    .Linq<Child>()
    .Where(c => c.Parent == parent)
    .Max(c => c.Number);
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);
    }
}
var maxNumber = session
    .Query<Child>()
    .Where(c => c.Parent.Id == parent.Id)
    .Max(c => c.Number);
使用如下映射:

var maxNumber = session
    .Linq<Child>()
    .Where(c => c.Parent == parent)
    .Max(c => c.Number);
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);
    }
}
var maxNumber = session
    .Query<Child>()
    .Where(c => c.Parent.Id == parent.Id)
    .Max(c => c.Number);
如何使用NHibernate重写它以获得后一个输出?这是在存储库方法中完成的,因此如果需要,我可以轻松地切换到HQL或其他方法,如果其他方法都失败,当然也可以切换到普通的DbCommand


我正在将NHibernate 2.0与LINQ to NHibernate和SQL Server 2008 R2一起使用。

当我创建查询并明确指定Id是我要查询的属性,而不是我得到优化查询的实体时。i、 e:

session
    .Query<Child>()
    .Where(c => c.Parent.Id = parent.Id)
    .Max(c = c.Number);
如果您使用的是查询,那么就不能使用NHibernate2.0

假设这是一个输入错误,而你的意思是3.0,尝试更新到3.2。我刚刚验证了您的查询是否完全按照预期工作

现在,3.2中有一个bug,如果您这样编写查询,它会导致额外的连接:

var maxNumber = session
    .Linq<Child>()
    .Where(c => c.Parent == parent)
    .Max(c => c.Number);
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);
    }
}
var maxNumber = session
    .Query<Child>()
    .Where(c => c.Parent.Id == parent.Id)
    .Max(c => c.Number);

…这在3.3中得到了修复。从昨天开始,预发布版本已经发布了

Hm,我尝试过了,我很确定这给了我同样的结果,但我可能做错了什么,我现在就检查一下。编辑:不,它似乎不起作用。也许是@JayOtterbein提到的NH版本?我最终决定切换到NH3.2。NH2中的LINQ提供程序一直有缺陷。使用NH3.2我得到了优化的查询。我猜2.0在查询大楼中并没有那么智能。因此,我不确定HQL是否能解决这个问题。它是NH2,但我忘了提到我正在使用LINQ2NHibernate,它在v3 IIRC中与NH合并。旧的LINQ提供程序是使用session.LINQ访问的,而不是session.Query。NH3中的提供者是从零开始编写的,与旧的提供者完全无关,适用于最合理的情况。我建议你升级。好的,那是打字错误没关系,我在我的存储库方法中手动破解了DBCommand,因为它很短,而且是一个相对较旧的项目,所以我想避免在此时升级。