3

次の(簡略化された)階層があります。

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

NHibernate がサブクラスの SpecialItem を検出できるようにするために、アカウント マッピングで次のコードを使用します。

<discriminator column="Type" formula="Type"/>

SpecialItems にはマッピングで lazy="false" が設定されていますが、私の知る限り、LINQ クエリでは無視されます。

今、LINQを使用して呼び出すと

Session.Query<Account>().ToList();

SpecialItems が別のクエリでフェッチされていることがわかります。熱心に読み込んでいきたいと思います。

私はそれを使用してそれを行うことができました

Session.Query<Account>().FetchMany(a => a.SpecialItems).ToList();

しかし、問題があります - SpecialItems は SpecialAccount のプロパティです。したがって、 a が SpecialAccount クラスの場合にのみ FetchMany が機能する必要があります。

私は次のような醜いことさえ試しました:

Session.Query<Account>().
    FetchMany(a => (a is SpecialAccount ? (a as SpecialAccount ).SpecialItems : null));

しかし、NHibernate は別のクエリでまだ SpecialItems を選択していました。

単一のクエリで NHibernate に SpecialAccount の SpecialItems を選択させるにはどうすればよいですか?

追加情報

私は MS SQL Express 2012 を使用しており、NHibernate の構成には次の行があります。

<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 バージョン 3.2.0.4000

以下は、MS SQL プロファイラーに表示される Id=2 の既存の SpecialAccount に対して NHibernate によって生成されたクエリです (選択されたイベント 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
4

1 に答える 1

2

「条件付きフェッチ」はできません。少なくとも 2 つのクエリが必要です。

ただし、Future LINQ クエリを使用してそれらをグループ化できるため、実質的に 1 回のラウンドトリップになります。

session.Query<SpecialAccount>().FetchMany(x => x.SpecialItems).ToFuture();
var accounts = session.Query<Account>().ToFuture();

を列挙すると、両方のクエリが実行されますaccounts最初のクエリの結果を明示的に保存しませんがSpecialAccounts、対応するコレクションと共にメモリにロードされるSpecialItemsため、余分な DB 呼び出しはありません。

于 2012-08-28T14:54:33.120 に答える