如何在nhibernate查询中选择引用的实体

如何在nhibernate查询中选择引用的实体,nhibernate,select,lazy-loading,eager-loading,queryover,Nhibernate,Select,Lazy Loading,Eager Loading,Queryover,我有一个实体,其属性引用了示例中的其他实体ReferenceEntity 使用HQL,我可以做到这一点: select e.ReferenceEntity from Entity e where e.Id = :entityId NHibernate将为我提供引用实体实例,而不使用lazy 通过查询,我正在尝试执行以下操作: Session.QueryOver<Entity>() .Where(e => e.Id == entityId) .Select(e => e.

我有一个实体,其属性引用了示例中的其他实体ReferenceEntity

使用HQL,我可以做到这一点:

select e.ReferenceEntity from Entity e where e.Id = :entityId
NHibernate将为我提供引用实体实例,而不使用lazy

通过查询,我正在尝试执行以下操作:

Session.QueryOver<Entity>()
.Where(e => e.Id == entityId)
.Select(e => e.ReferenceEntity)
.SingleOrDefault<ReferenceEntity>()
对于QueryOver,Nhibernate给了我ReferenceEntity,但很懒

我想像使用hql一样,使用queryover获得带有急切加载的ReferenceEntity


谢谢

如果我理解正确,这就是您需要的:

Session.QueryOver<Entity>()
 .Where(e => e.Id == entityId)
 //!!!
 .Fetch(e=>e.ReferenceEntity).Eager
 .Select(e => e.ReferenceEntity)
 .SingleOrDefault<ReferenceEntity>()
试试这个:

Session.QueryOver<Entity>()
 .Where(e => e.Id == entityId)
 .Fetch(e=>e.ReferenceEntity).Eager
 .Select(e => e.ReferenceEntity)
 .TransformUsing(Transformers.AliasToBean<ReferenceEntity>())
 .SingleOrDefault<ReferenceEntity>()
建议1 在执行查询之后,您可以执行一点LINQ操作来获取所需的数据

var result = Session.QueryOver<Entity>()
    .Where(e => e.Id == entityId)        // Filter,
    .Fetch(e => e.ReferenceEntity).Eager // join the desired data into the query,
    .List()                              // execute database query,
    .Select(e => e.ReferenceEntity)      // then grab the desired data in-memory with LINQ.
    .SingleOrDefault();
Console.WriteLine("Name = " + result.Name);
建议2 另一种方法是使用EXISTS子查询,这会稍微复杂一些,但会在第一次返回正确的结果,而无需任何后期数据库操作:

ReferenceEntity alias = null;
var result = Session.QueryOver(() => alias)
    .WithSubquery.WhereExists(QueryOver.Of<Entity>()
        .Where(e => e.Id == entityId)                 // Filtered,
        .Where(e => e.ReferenceEntity.Id == alias.Id) // correlated,
        .Select(e => e.Id))                           // and projected (EXISTS requires a projection).
    .SingleOrDefault();
Console.WriteLine("Name = " + result.Name);

你好我照你说的做了,但没用。QueryOver正在向我返回Castle.Proxy.GroupProxy。NHibernate正在执行此查询:选择此组id作为y0,从中发布此内容,其中此内容id=:p0;:p0=72。我想要一个团体。有了Hql,我可以获得实体。谢谢似乎对我不起作用。生成的SQL仅投影被引用实体的标识符:从实体this中选择this_2;ReferenceEntityId为y0_2;,其中this_2;.Id='a67b894e-bc53-e011-bd88-22a08ed629e5'您的第一个建议会导致和可能的性能问题。第二个可能只生成一个DB查询,但在这个查询中,您将看到WHERE EXISTS,根据RDBMS的不同,这可能会导致相同的不希望出现的复杂性。我希望使用QueryOver表达式,通过简单的SELECT将所有字段从已连接的ReferenceEntity表中投影出来。经过编辑以包含NHibernate执行的实际查询。这两种方法都只执行一个查询。您可以发布导致选择N+1的测试吗?您的目标是哪个数据库服务器?SQL Server为这两个查询生成几乎相同的查询计划—它显示了EXISTS查询实际上使用了一个隐藏的内部联接,因此在某些情况下,它可能实际上比另一个查询更快。您显然是对的。我没有很好地理解你的第一个问题,错过了Fetch.Eager子句。很抱歉。非常感谢您使用生成的SQL记录查询并提供SQL Server洞察。这里有110个代表-不要一下子花光;
ReferenceEntity alias = null;
var result = Session.QueryOver(() => alias)
    .WithSubquery.WhereExists(QueryOver.Of<Entity>()
        .Where(e => e.Id == entityId)                 // Filtered,
        .Where(e => e.ReferenceEntity.Id == alias.Id) // correlated,
        .Select(e => e.Id))                           // and projected (EXISTS requires a projection).
    .SingleOrDefault();
Console.WriteLine("Name = " + result.Name);
SELECT this_.Id as Id1_0_, this_.Name as Name1_0_
FROM [ReferenceEntity] this_
WHERE exists (
    SELECT this_0_.Id as y0_
    FROM [Entity] this_0_
    WHERE this_0_.Id = @p0 and this_0_.ReferenceEntity_id = this_.Id);