基本的な質問:Fluent NHibernateで双方向の1対多のマップを作成するにはどうすればよいですか?
詳細:
多くの子供を持つ親オブジェクトがあります。私の場合、子が親を持たないのは意味がないので、データベースでは、親への外部キーにNOT NULL制約を設定します。 Fluent NHibernateマッピングからデータベースを自動生成しています。
私はそのような多くの子オブジェクトを持つ親を持っています:
public class Summary
{
public int id {get; protected set;}
public IList<Detail> Details {get; protected set;}
}
public class Detail
{
public int id {get; protected set;}
public string ItemName {get; set;}
/* public Summary Owner {get; protected set;} */ //I think this might be needed for bidirectional mapping?
}
これが私が始めたマッピングです:
public class SummaryMap : ClassMap<Summary>
{
public SummaryMap()
{
Id(x => x.ID);
HasMany<Detail>(x => x.Details);
}
}
public class DetailMap : ClassMap<Detail>
{
public DetailMap()
{
Id(x => x.ID);
Map(x => x.ItemName).CanNotBeNull();
}
}
Detailテーブルでは、Summary_idはNull以外にする必要があります。これは、私の場合、Detailオブジェクトが集計オブジェクトにアタッチされていなくても意味がないためです。ただし、HasMany()マップを使用するだけでは、Summary_id外部キーはヌル値のままになります。
NHibernateのドキュメント( http://www.hibernate.org/hib_docs/nhibernate/html/collections.html )で、「親が必要な場合は、双方向の1対多協会"。
では、どうすればFluent NHibernateで双方向の1対多のマップを作成できますか?
Detailsテーブルのnull以外の外部キー列との双方向の関連付けを取得するには、推奨されるOwnerプロパティ、References(...)。CanNotBeNull()マッピングをDetailsMapクラスに追加し、Summaryを逆にします。
2つの関連付け方向に2つの異なる外部キー列が存在しないようにするには、手動で列名を指定するか、両方向に同じ列名を与えるような方法でプロパティに名前を付けます。この場合、Details.Ownerプロパティの名前をDetails.Summaryに変更することをお勧めします。
現在のところSummaryにはID以外の列がないため、テーブルに挿入するときの問題を回避するために、インクリメントによって生成されたSummary IDを作成しました。
ドメイン:
public class Detail
{
public int id { get; protected set; }
public string ItemName { get; set; }
// Renamed to use same column name as specified in the mapping of Summary.Details
public Summary Summary {get; set;}
}
public class Summary
{
public Summary()
{
Details = new List<Detail>();
}
public int id { get; protected set; }
public IList<Detail> Details { get; protected set; }
}
マッピング:
public class DetailMap : ClassMap<Detail>
{
public DetailMap()
{
Id(x => x.id)
.GeneratedBy.Native();
Map(x => x.ItemName)
.CanNotBeNull();
References<Summary>(x => x.Summary)
// If you don't want to rename the property in Summary,
// you can do this instead:
// .TheColumnNameIs("Summary_id")
.CanNotBeNull();
}
}
public class SummaryMap : ClassMap<Summary>
{
public SummaryMap()
{
Id(x => x.id)
.GeneratedBy.Increment();
HasMany<Detail>(x => x.Details)
.IsInverse()
.AsBag(); // Use bag instead of list to avoid index updating issues
}
}