nhibernateselectlazy-loadingeager-loadingqueryover

How select referenced entity in nhibernate queryover


I Have a entity with a property referencing other entity (ReferenceEntity in examples).

With HQL i can do this:

select e.ReferenceEntity from Entity e where e.Id = :entityId

NHibernate will give me the ReferenceEntity instance without lazy.

With query over im trying do this:

Session.QueryOver<Entity>()
.Where(e => e.Id == entityId)
.Select(e => e.ReferenceEntity)
.SingleOrDefault<ReferenceEntity>()

With QueryOver Nhibernate is giving me the ReferenceEntity but lazy.

I wanna get ReferenceEntity with eager loading using queryover like i do with hql.

Thanks


Solution

  • Suggestion #1

    You could do a little bit of LINQ manipulation after you execute the query to grab the data you want.

    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);
    

    It's simple and gets the job done.

    In my test, it resulted in a single query. Here's the output:

    SELECT
        this_.Id as Id0_1_, this_.Name as Name0_1_, this_.ReferenceEntity_id as Referenc3_0_1_,
        q5379349_r2_.Id as Id1_0_, q5379349_r2_.Name as Name1_0_
    FROM
        [Entity] this_
        left outer join [ReferenceEntity] q5379349_r2_
            on this_.ReferenceEntity_id=q5379349_r2_.Id
    WHERE this_.Id = @p0;
    

    Suggestion #2

    Another approach would be to use an EXISTS subquery, which would be slightly more complex, but would return the right result the first time without any need for post-database manipulation:

    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);
    

    Tested - results in single query:

    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);