12

現在のプロジェクトに奇妙な問題があります。クエリの遅延読み込みが機能しません。リストをクエリすると、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>
4

1 に答える 1

13

かなりの調査の後、私は答えを見つけました。答えは、NHibernate での遅延読み込みを防ぐことができるものがたくさんあるためです。

  1. クエリと session.Load の比較:アイテムをsession.Load()取得すると、プロキシが取得されます。しかし、任意のプロパティにアクセスするとすぐにUrl、遅延読み込みをサポートしていないすべての関連付けを含めて、オブジェクトがフェッチされます。

  2. property-ref:遅延読み込みは、オブジェクト ID に対してのみ機能します。プロパティの関連付けがターゲット エンティティの別の列を介して解決されると、NH はそれを熱心にフェッチします。これが不可能というわけではありませんが、実装されていないだけです:バグ

  3. not-found="ignore"無効な外部キーを許可します。つまり、参照されるエンティティが見つからない場合、NH はプロパティを null で初期化します。NH は、遅延読み込みのためにプロパティ アクセスをインターセプトしませんが、代わりにオブジェクト プロキシを割り当てます。プロパティをnullに設定するか、指定された、おそらく無効な外部キーのプロキシに設定するかをnot-found="ignore"決定できません。これは、プロパティへのアクセスを傍受することで解決できる可能性があります。

  4. 無効にするnot-found="ignore"property-ref、スキーマのエクスポートにより、循環参照を強制する制約が生成されます。良くない!正しいマッピングは、制約付きの 1 対 1 の関係になります。この場合、 for のキーにHippoAccountSyncは generator が必要foreignです。

資力

于 2009-10-30T12:31:35.177 に答える