Reputation: 13723
I have a following (simplified) hierarchy:
class Account
{
AccountType Type;
long Id;
string Name;
}
public enum AccountType
{
UsualAccount = 0,
SpecialAccount = 1
}
class SpecialAccount : Account
{
List<SpecialItem> SpecialItems;
}
class SpecialItem
{
long Id;
string Name;
}
To help NHibernate to detect subclass SpecialItem, I use the following code in the Account mapping:
<discriminator column="Type" formula="Type"/>
and SpecialItems have lazy="false" set in the mapping, but as far as I know, it is ignored during LINQ queries.
Now when I use LINQ and call
Session.Query<Account>().ToList();
I see that SpecialItems are fetched in a separate query. I would like to load them eagerly.
I could do that using
Session.Query<Account>().FetchMany(a => a.SpecialItems).ToList();
but there is a problem - SpecialItems is the property of the SpecialAccount. So I somehow need FetchMany to work only if a is a SpecialAccount class.
I tried even something as ugly as:
Session.Query<Account>().
FetchMany(a => (a is SpecialAccount ? (a as SpecialAccount ).SpecialItems : null));
but NHibernate still selected SpecialItems in a separate query.
How can I make NHibernate select SpecialItems for SpecialAccount in a single query?
Additional information
I am using MS SQL Express 2012 and NHibernate configuration has the following lines:
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<property name="adonet.batch_size">50</property>
<property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property>
NHibernate.dll version 3.2.0.4000
Here are the queries generated by NHibernate for one existing SpecialAccount with Id=2, as they appear in MS SQL Profiler (with selected events RPCCompleted, Exec Prepared SQL, SQL:StmtCompleted):
select account0_.Id as Id5_, account0_.Type as Type5_, account0_.Name as Name5_, account0_.Type as clazz_ from tAccount account0_
exec sp_executesql N'SELECT specialite0_.AccountId as Id1_, specialite0_.Id as specialite1_1_, specialite0_.Id as specialite1_13_0_, specialite0_.Name as Name13_0_
FROM tSpecialItem specialite0_ WHERE specialite0_.Id=@p0',N'@p0 bigint',@p0=2
Upvotes: 3
Views: 1520
Reputation: 52745
You can't to a "conditional fetch". You need at least two queries.
You can, however, group them using a Future LINQ query, so it would be effectively one roundtrip:
session.Query<SpecialAccount>().FetchMany(x => x.SpecialItems).ToFuture();
var accounts = session.Query<Account>().ToFuture();
Both queries run when you enumerate accounts
. We don't store the results of the first query explicitly, but the SpecialAccounts
are loaded in memory with their corresponding SpecialItems
collections, so there are no extra DB calls.
Upvotes: 2