現実はもっと複雑です。 session.Load
を使用してエンティティをロードするか、遅延ロードされたプロパティにアクセスすると、NHibernateはプロキシオブジェクトを返します。そのプロキシオブジェクトは、そのプロパティのいずれかに初めてアクセスしたときに、水和(データはDBからロードされます)されます。これを実現するために、NHibernateはを拡張してエンティティクラスを継承し、すべてのプロパティゲッターとセッターをオーバーライドするプロキシクラスを生成します。プロキシとエンティティクラス(プロキシベースクラス)を区別する方法がないため、継承を使用しないと完全に機能します。単純なテストproxy is MyEntity
は常に動作します。
class Person {
// lazy-loaded
public Animal Pet { get; set; }
}
そして、我々はまた、Animal
クラス階層を持っている:あなたは人のためにNHibernateのを頼むとき
public abstract class Animal { ... }
public class Cat { ... }
public class Dog { ... }
は今、Pet
プロパティは遅延ロードされていることを前提と
今、私たちはPersonエンティティを持っていることを想像しますあなたはプロキシオブジェクトを取得します:
var pet = somePerson.Pet; // pet will be a proxy
Pet
は遅延読み込みプロパティなので、NHはCat
またはのインスタンスになるかどうかわからないので、最善を尽くしてAnimal
を拡張するプロキシを作成します。プロキシはpet is Animal
のテストに合格しますが、pet is Cat
またはpet is Dog
のいずれかのテストに失敗します。
pet
オブジェクトのいくつかのプロパティにアクセスし、NHが強制的にデータをDBからロードするとします。 NHはあなたのペットが、 Cat
ですが、プロキシはすでに生成されており、変更することはできません。 これは、Animal
を拡張するpet
の元のプロキシがCat
に絞り込まれるという警告をHibernateに出させます。これは今からからの代理オブジェクトpet.Id
を使用して作成したもので、session.Load<Animal>(pet.Id)
はCat
になります。これは、Cat
がセッションの一部として保存されているため、最初にcatを共有する第2の人物を読み込んだ場合、NHは既に使用可能なCat
プロキシインスタンスを使用して遅延読み込みプロパティを設定します。
pet
へのオブジェクト参照がsession.Load<Animal>(pet.Id)
(object.ReferencesEqual
の意味で)と異なることになります。これはあなたに害を引き起こす可能性が今
:
あなたがSet
のかDictionary
あなたのコード内で居住またはにあなたのエンティティを置くあなたは仕事にEquals/GetHashCode
ペアを必要とする他の構造を使用している場合。これは、カスタムEquals/GetHashCode
の実装を提供することで簡単に修正できます(http://www.onjava.com/pub/a/onjava/2006/09/13/dont-let-hibernate-steal-your-identity.html?page=1参照)
プロキシオブジェクトをターゲットタイプにキャストしようとすると、 (Cat)pet
が、再び
だから道徳的は、ドメインモデルで可能な限り継承を避けるためである(例えば
Getting proxies of the correct type in NHibernate)ソリューションが知っています。
これは大きな問題ですか?このWARNを無視するとどうなりますか? – Beatles1692
これは大きな問題であり、受け入れるリスクのレベルによって異なります。あなたのコードとデータベースとの間には常に切り離しがあるので、いつでも確実にキャスティングが動作するとは限りません。これにより、診断が難しく、データベースやコードを変更することなく解決できないバグが発生します。 – Fourth