NHibernateとC#は初めてなので、優しくしてください。
私は次の2つのNHibernateエンティティを持っています:
Employee
{
private long _id;
private String _name;
private String _empNumber;
private IList<Address> _addresses;
//Properties...
}
そして
Address
{
private long _id;
private String _addrLine1;
private String _addrLine2;
private String _city;
private String _country;
private String _postalCode;
//Properties
}
そして彼らはone-to-many
Employee
からAddress
への関係(各従業員はレコードに複数のアドレスを持つことができます)。複数の従業員が同じ住所に住んでいる可能性があるという事実を無視すると便利です。
私はこれをメモリ内のオブジェクト(NHibernateエンティティ)の観点から理解しています。私が苦労しているのはマッピングファイルです(そしてここでは簡単な例を取り上げています)。これは私がこれまでに思いついたものです:
// Intentionally left out XML and <hibernate-mapping>
// Mappings for class 'Employee'. -->
<class name="Employee" table="Employees">
<id name="ID">
<generator class="native">
</id>
<property name="Name" />
<property name="EmpNumber" />
<bag name="Addresses">
<key column="AddressId" />
<one-to-many class="Address" />
</bag>
</class>
そして
// Intentionally left out XML and <hibernate-mapping> .
// Mappings for class 'Address'
<class name="Address" table="Addresses">
<id name="ID">
<generator class="native">
</id>
// Intentionally left out name="Employee"
// as I don't have corresponding field in Address entity.
<many-to-one class="Employee" column="EmployeeID" cascade="all" />
<property name="AddrLine1" />
<property name="AddrLine2" />
<property name="City" />
<property name="Country" />
<property name="PostalCode" />
</class>
Address
エンティティへの参照であるEmployee
エンティティのフィールドのようです。しかし、そうであれば、なぜこれが必要なのか理解できません。Address
からEmployee
をフェッチする必要はなく、その逆だけです...NHibernateを使用して作業したときに見つけた最も適切な標準を要約した、ほんの少しのヒント。
1)persitence(DB列)に双方向参照がある場合は、 _C#
_コード双方向も同様です。
言い換えると、子が親を参照している場合、親は子への参照。
_public class Employee
{
...
public virtual IList<Address> { get; set; }
}
public class Address
{
...
public virtual Employee Employee { get; set; }
}
_
これは、ビジネスドメインをそのまま表します。住所は従業員に属し、従業員は住所に属します。
何らかの理由でそれを本当に制限したい場合は、
protected
修飾子を使用する必要がありますが、参照は_C#
_に保持します。
2)_inverse="true"
_を使用します。これは、(上記のように)両側をマッピングした場合にのみ使用でき、より「期待され最適化された」INSERTおよびUPDATEスクリプトにつながります。
詳細はこちら:
逆=「真の」例と説明 mkyong
3)ほぼすべての場所でバッチフェッチマッピングを使用します。これにより、クエリ中の1 + Nの問題が回避されます。続きを読む:
4)一方のオブジェクト_(in our case Employee)
_がroot
である場合(もう一方はそれなしではあまり意味がありません)-カスケードを使用します。続きを読む:
nhibernate-親を更新して子を作成しますか、それとも明示的に作成しますか?
マッピングスニペットのルール2、3、4:
_<class name="Employee" ... batch-size="25">
...
<bag name="Addresses"
lazy="true"
inverse="true"
batch-size="25"
cascade="all-delete-Orphan" >
// wrong! This columns is the same as for many-to-one
//<key column="AddressId" />
// it is the one column expressing the relation
<key column="EmployeeId" />
<one-to-many class="Address" />
</bag>
<class name="Address" ... batch-size="25">
...
<many-to-one not-null="true" name="Employee" column="EmployeeID" />
_
3)_inverse="true
_を使用する場合は、関係の両側を割り当てることを忘れないでください(作成時に最も重要)
その理由は:
nHibernateに指示します-反対側(
Address
)は関係を維持する責任があります。ただし、これを適切に行うには、そのAddress
がEmployee
を参照している必要があります。これにより、IDをAddressテーブルの列に保持できます。
したがって、これは新しいアドレスを作成するための標準コードである必要があります
_Employee employee = ... // load or create new
Address address = new Address
{
...
Employee = employee, // this is important
};
Employee.Addresses.Add(address);
session.SaveOrUpdate(employee); // cascade will trigger the rest
_
この複雑さを隠すAddAddress()
のようなメソッドを導入することもできますが、両側を設定することは良い方法です。
カスケードall-delete-Orphan
をone-to-many
関係に追加する必要があります。Employee
を削除すると、アドレスも削除されます。
Employee
参照が必要ない場合は、次のようなinverse=false
関係を作成します。 ここ