自動マッピングで Fluent Nhibernate を使用していますが、現在の継承のために双方向の HasMany 関係を設定する際に問題があります。
私のコードの単純化されたバージョンは次のようになります
public abstract class BaseClass
{
public BaseClass Parent { get; set; }
}
public class ClassA : BaseClass
{
public IList<ClassB> BChilds { get; protected set; }
public IList<ClassC> CChilds { get; protected set; }
}
public class ClassB : BaseClass
{
public IList<ClassD> DChilds { get; protected set; }
}
public class ClassC : BaseClass
{
}
public class ClassD : BaseClass
{
}
すべてのクラスは 1 つの親を持つことができ、一部の親は 2 つのタイプの子を持つことができます。テーブルになるタイプごとのテーブル継承を使用しています
- 「ベースクラス」
- 「クラスA」
- 「クラスB」
- 「クラスC」
- 「クラスD」
機能する双方向マッピングを取得するために、次のオーバーライドを行いました (ClassA の 1 つの例)。
mapping.HasMany<BaseType>(x => x.BChilds).KeyColumn("Parent_Id");
mapping.HasMany<BaseType>(x => x.CChilds).KeyColumn("Parent_Id");
これは、子の型が 1 つしかないクラスでは正常に機能しますが、子の型が 2 つある ClassA は、各リストで BaseType のすべてのサブタイプを取得し、もちろん例外になります。私は2つの異なる回避策を見てきましたが、どれも本当に十分ではないと感じており、それを解決するためのより良い方法があると本当に信じています.
回避策 1: HasMany マッピングで具体的なサブタイプを指定します。(より多くの情報で更新)
mapping.HasMany<ClassB>(x => x.BChilds).KeyColumns("Parent_Id");
(BaseType を ClassB に置き換え)
このマッピングにより、NHibernate は場合によっては ClassB テーブルで Parent_Id という名前の列を探しますが、明らかに BaseClass テーブルに属しているため、そのような列はありません。この問題は、ClassA 選択時に BChilds に基づくステートメントを追加した場合にのみ発生します。たとえば、ClassA のエンティティをロードしてから ClassA.BChilds を呼び出すと動作するように見えますが、(NhibernateLinq を使用して) 次のようなクエリを実行します。
Query<ClassA>().Where(c => c.BChilds.Count == 0)
間違ったテーブルが使用されます。したがって、このテーブルに同じ名前の新しい列を手動で作成し、すべての値をコピーする必要があります。機能しますが、リスクが高く、柔軟性がまったくありません。
回避策 2:具象型を示す BaseClass に列を追加し、HasMany マッピングに where ステートメントを追加します。
(回避策1への更新後、これが実行可能な解決策になるかどうかわかりません)
列を追加することで、discriminatorValue で階層ごとのテーブル継承を使用する場合と同じ方法で実行できます。つまり、BaseType テーブルは ClassA、ClassB の値を持つ新しい列を取得します... NHibernate が継承全体をどれだけ適切に処理しているかを考えると、NHibernate のマニュアルを読むことで、型ごとのテーブルにディスクリミネーターは必要ないと思いますシナリオでは、Nhibernate はすでに難しい部分を行っているようで、新しい列を追加せずにクリーンな方法でこれを処理できるはずですが、方法がわかりません。