NHibernateは、LinqまたはCriteria API経由ではなく、session.Load()経由でプロキシを作成します
-
10-07-2019 - |
質問
現在のプロジェクトに奇妙な問題があります。クエリの遅延読み込みは機能しません。リストを照会すると、nhibernateはすべての関連付けを個別にフェッチします。
その小さな部分を抽出し、別のソリューションに入れました。基本的に私が持っているのは、Account-TableとAccountSync-Tableです。どちらにもIDとURLがありますが、IDは単なるdb-guidです。
クラスは:
public class HippoAccount
{
public virtual Guid Id { get; set; }
public virtual string Url { get; set; }
public virtual HippoAccountSync Sync { get; set; }
}
public class HippoAccountSync
{
public virtual Guid Id { get; set; }
public virtual string Url { get; set; }
public virtual HippoAccount Account { get; set; }
}
GUIDを介してオブジェクトをロードするとき:
var account = session.Load<HippoAccount>(accountId);
Console.WriteLine(NHibernateUtil.IsPropertyInitialized(account, "Sync"))
... false
を返し、アカウント自体がプロキシです。
ただし、条件APIを使用してリストを読み込む場合:
var account = (HippoAccount)session
.CreateCriteria(typeof (HippoAccount))
.Add(Restrictions.Eq("Id", accountId))
.List()[0];
...プロパティ Sync
は初期化され(2番目の選択クエリを起動)、返されたオブジェクトはプロキシではありません。
デフォルトの動作ですか?何が間違っているのですか?
マッピングは次のとおりです。
<class name="HippoAccount" table="AllAccounts">
<id name="Id" type="guid">
<generator class="guid"/>
</id>
<property name="Url" />
<many-to-one
class="HippoAccountSync"
name="Sync"
not-found="ignore"
property-ref="Url">
<column name="url" />
</many-to-one>
</class>
<class name="HippoAccountSync"
mutable="false"
table="Accounts">
<id name="Id" type="guid">
<generator class="guid"/>
</id>
<property name="Url">
<column name="serviceUri" />
</property>
<many-to-one class="HippoAccount"
name="Account"
property-ref="Url"
not-found="ignore">
<column name="serviceUri" />
</many-to-one>
</class>
解決
さらに調査を重ねた結果、答えが見つかりました。回答。NHibernateの遅延読み込みを防ぐことができるものがたくさんあるからです。
-
Query vs. session.Load:
session.Load()
を介してアイテムを取得すると、プロキシが取得されます。ただし、任意のプロパティにアクセスするとすぐに、Url
と言うと、遅延読み込みをサポートしないすべての関連付けを含むオブジェクトがフェッチされます。 -
property-ref:遅延読み込みはオブジェクトIDに対してのみ機能します。プロパティの関連付けがターゲットエンティティの別の列を介して解決されると、NHはそれを積極的にフェッチします。 これは不可能ではなく、実装されていないだけではありません:バグ
-
not-found =&quot; ignore&quot; は、無効な外部キーを許可します。つまり、参照されたエンティティが見つからない場合、NHはプロパティを初期化しますヌル。 NHは、遅延読み込みのプロパティアクセスをインターセプトせず、代わりにオブジェクトプロキシを割り当てます。
not-found =&quot; ignore&quot;
を使用すると、プロパティをnullに設定するか、指定された(場合によっては無効な)外部キーのプロキシに設定するかを決定できません。 これは、プロパティアクセスをインターセプトすることで解決できる可能性があります。 -
not-found =&quot; ignore&quot;
およびproperty-ref
を無効にすると、スキーマのエクスポートにより、循環参照を強制する制約が生成されます。良くない!正しいマッピングは、制約された1対1の関係になります。この場合、HippoAccountSync
のキーにはジェネレーターforeign
が必要です。
リソース