2009-03-02 8 views
17

NHibernateを使用してマッピングしている従来のデータベースがあります。問題のオブジェクトは、AccountとNotificationオブジェクトのリストです。私は私がセレクトN + 1ケースを取得しています、このようなproperty-refを使用してキー以外のフィールドにマッピングするとき、多対一関係でレイジーロードが機能しない

return session.CreateCriteria(typeof(Notification)).List<Notification>(); 

などの基準を作成するときに、しかし

<class name="Account" table="Account" dynamic-update="true"> 
<id name="Id" column="AccountID"> 
    <generator class="native" /> 
</id> 
<property name="AccountNumber" length="15" not-null="true" /> 
    <!-- other properties --> 
</class> 

<class name="Notification" table="Notification"> 
    <id name="Id" column="Id"> 
     <generator class="native" /> 
    </id> 
    <!-- other properties --> 
    <many-to-one name="Account" class="Account" property-ref="AccountNumber" lazy="proxy"> 
     <column name="AcctNum" /> 
    </many-to-one> 

:マッピングファイルがどのように見える

public class Notification 
{ 
    public virtual int Id { get; set; } 
    public virtual DateTime BatchDate { get; set; } 
    /* other properties */ 

    public virtual Account Account { get; set; } 
} 

public class Account 
{ 
    public virtual int Id { get; set; } 
    public virtual string AccountNumber { get; set; } 
    /* other properties */ 
} 

:オブジェクトは、次のようになりアカウントが決して参照されなくても、各アカウントがロードされます。多対1が遅延プロキシとしてマップされていると、すべてのアカウントがロードされるのはなぜですか?

+0

私は同じ問題を取得し、私は多対一のプロパティのREFのは、遅延ロードすることはできませんと言ってsomehwereポストを見て覚えていますか私はソースを見つけることができません。これはNHとありました1.2 – Jafin

答えて

13

この問題は、property-ref属性によって発生します。レイジーローディングは、many-to-one参照が他のオブジェクトのプライマリキーを使用している場合にのみ機能します。これは、Hibernateがそのような値の有効性を強制する外部キー制約があると仮定しているからです。非プライマリキー(property-refで示される)では、NHibernateはこの前提を作らないので、関連するオブジェクトが存在しなければならないと仮定しません。存在しないオブジェクト(つまり、プロキシではなくヌル)のプロキシを作成したくないので、リモートオブジェクトを熱心に取得します。 not-found="ignore"が指定されている場合、外部キーの関係が強制されておらず、null参照が発生する可能性があることを示すため、同じ問題が発生します。

も参照してください:

+0

NHの問題はTwoPhaseLoad.csにあるようです - それはLoadedStateを検査し、KEYをエンティティまたはプロキシに変換するためにIType.ResolveIdentifierを呼び出します。ここに関わるITypeはManyToOneです(PK = false、Uniq = true、eager = false)。これは、基本EntityType.csからResolveIdentifier(value、session、owner)を呼び出して終了し、IsReferenceToPrimaryKey(= false)をチェックしてLoadByUniqueKey()を呼び出します。これは、順番に興味深いコメント "TODO:implement caching?proxy?" (わーい)。次に、session.PersistenceContext.GetEntity(新しいEntityUniqueKey(.. key))+ persister.LoadByUniqueKey(.. key)のコンボでエンティティを取得します。 – quetzalcoatl

関連する問題