Nhibernate-cascades
NHibernate-カスケード
この章では、カスケード機能の使用方法について説明します。 アイテムのセットまたはコレクション、または顧客と注文などの2つのクラス間の関係があり、外部キー関係がある場合。 デフォルトで顧客を削除すると、NHibernateは子オブジェクトに対して何もしません。そのため、その顧客に属するオブジェクトは孤立した注文になる可能性があります。
- 外部キー制約に違反している可能性もあるため、カスケードの概念を使用できます。
- デフォルトでは、NHibernateは操作を子オブジェクトにカスケードしません。
- これは、デフォルトの配送先住所を持つ顧客などの関係を持つことができ、その配送先住所が多くの異なる顧客と共有されるためです。
- そのため、他の顧客がまだ関係を参照しているため、その関係を必ずしもカスケードすることは望ましくありません。
- したがって、カスケードの全体的な概念は、NHibernateに子エンティティーの処理方法を伝えることです。
カスケードには、次のようなさまざまなオプションがあります-
none -これはデフォルトであり、カスケードなしを意味します。
all -保存、更新、削除をカスケードします。
save-update -カスケード、保存、更新します。
delete -削除をカスケードします。
all-delete-orphan -これは非常に頻繁に使用される特別なもので、All Exceptと同じです。Delete-orphan行が見つかった場合は、それらも削除されます。
*hbm.xml* ファイルでデフォルトを指定できるため、そのHibernateマッピング要素にデフォルトのカスケードを提供したり、多対1などの特定のコレクションおよび関係に対してデフォルトのカスケードを指定したりできます。
簡単なカスケードの例を見てみましょう。プログラムの問題を修正しましょう。次のコードに示すように、保存をオーダーに手動でカスケードする必要があります。
using(var session = sessionFactory.OpenSession())
using(var tx = session.BeginTransaction()) {
var newCustomer = CreateCustomer();
Console.WriteLine("New Customer:");
Console.WriteLine(newCustomer);
session.Save(newCustomer);
foreach (var order in newCustomer.Orders) {
session.Save(order);
}
id = newCustomer.Id;
tx.Commit();
}
上記のコードスニペットでは、顧客のすべての注文を手動で保存していることがわかります。 次に、すべての注文が保存されている手動カスケードコードを削除しましょう。
using(var session = sessionFactory.OpenSession())
using(var tx = session.BeginTransaction()) {
var newCustomer = CreateCustomer();
Console.WriteLine("New Customer:");
Console.WriteLine(newCustomer);
session.Save(newCustomer);
id = newCustomer.Id;
tx.Commit();
}
*customer.hbm.xml* でカスケードオプションを指定する必要があります。
<?xml version = "1.0" encoding = "utf-8" ?>
<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" assembly = "NHibernateDemo"
namespace = "NHibernateDemo">
<class name = "Customer">
<id name = "Id">
<generator class = "guid.comb"/>
</id>
<property name = "FirstName"/>
<property name = "LastName"/>
<property name = "AverageRating"/>
<property name = "Points"/>
<property name = "HasGoldStatus"/>
<property name = "MemberSince" type = "UtcDateTime"/>
<property name = "CreditRating" type = "CustomerCreditRatingType"/>
<component name = "Address">
<property name = "Street"/>
<property name = "City"/>
<property name = "Province"/>
<property name = "Country"/>
</component>
<set name = "Orders" table = "`Order`" cascade = "all-delete-orphan">
<key column = "CustomerId"/>
<one-to-many class = "Order"/>
</set>
</class>
</hibernate-mapping>
- 現在、注文は完全に顧客のものです。 したがって、顧客がデータベースから削除された場合、ここでのアプリケーションは、孤立している可能性のある注文を含め、これらの注文をすべて削除する必要があります。
- 削除を行うことになります。 それにより、顧客IDが削除する顧客と等しい注文テーブルから削除します。 したがって、これらの削除を実際にカスケードできます。 All *を使用すると、保存、更新、削除が実行されます。
このアプリケーションを実行すると、次の出力が表示されます。
New Customer:
John Doe (00000000-0000-0000-0000-000000000000)
Points: 100
HasGoldStatus: True
MemberSince: 1/1/2012 12:00:00 AM (Unspecified)
CreditRating: Good
AverageRating: 42.42424242
Orders:
Order Id: 00000000-0000-0000-0000-000000000000
Order Id: 00000000-0000-0000-0000-000000000000
Reloaded:
John Doe (10b2a3d7-7fcf-483c-b1da-a5bb00b8512e)
Points: 100
HasGoldStatus: True
MemberSince: 1/1/2012 12:00:00 AM (Utc)
CreditRating: Good
AverageRating: 42.4242
Orders:
Order Id: e6680e30-5b3b-4efa-b017-a5bb00b85133
Order Id: b03858e7-8c36-4555-8878-a5bb00b85134
The orders were ordered by:
John Doe (10b2a3d7-7fcf-483c-b1da-a5bb00b8512e)
Points: 100
HasGoldStatus: True
MemberSince: 1/1/2012 12:00:00 AM (Utc)
CreditRating: Good
AverageRating: 42.4242
Orders:
Order Id: e6680e30-5b3b-4efa-b017-a5bb00b85133
Order Id: b03858e7-8c36-4555-8878-a5bb00b85134
John Doe (10b2a3d7-7fcf-483c-b1da-a5bb00b8512e)
Points: 100
HasGoldStatus: True
MemberSince: 1/1/2012 12:00:00 AM (Utc)
CreditRating: Good
AverageRating: 42.4242
Orders:
Order Id: e6680e30-5b3b-4efa-b017-a5bb00b85133
Order Id: b03858e7-8c36-4555-8878-a5bb00b85134
Press <ENTER> to exit...
ご覧のとおり、手動でカスケードされたプログラムからコードを削除しましたが、アプリケーションは引き続き動作しています。
したがって、関係によっては、それらをカスケードすることもできます。 次に、別のカスケード関係を見てみましょう。 Order.hbm.xml ファイルに移動して、その多対1の関係をカスケードできます。
<?xml version = "1.0" encoding = "utf-8" ?>
<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" assembly = "NHibernateDemo"
namespace = "NHibernateDemo">
<class name = "Order" table = "`Order`">
<id name = "Id">
<generator class = "guid.comb"/>
</id>
<property name = "Ordered"/>
<property name = "Shipped"/>
<component name = "ShipTo">
<property name = "Street"/>
<property name = "City"/>
<property name = "Province"/>
<property name = "Country"/>
</component>
<many-to-one name = "Customer" column = "CustomerId" cascade = "save-update"/>
</class>
</hibernate-mapping>
したがって、新しい注文を作成し、それに新しい顧客がアタッチされ、その注文を保存すると言うと、それをカスケードすることができます。 しかし、おそらくしたくないことの1つは、対応する顧客を削除するために注文が削除された場合です。
そのため、ここでは保存更新を行いたいので、保存更新を使用して、保存または更新をその顧客にカスケードします。 したがって、新しい顧客を獲得した場合、または顧客を変更している場合、それはカスケードされます。 削除の場合、データベースからは削除されません。
したがって、アプリケーションを再度実行しても、すべてが期待どおりに機能します。
New Customer:
John Doe (00000000-0000-0000-0000-000000000000)
Points: 100
HasGoldStatus: True
MemberSince: 1/1/2012 12:00:00 AM (Unspecified)
CreditRating: Good
AverageRating: 42.42424242
Orders:
Id: 00000000-0000-0000-0000-000000000000
Order Id: 00000000-0000-0000-0000-000000000000
Reloaded:
John Doe (10b2a3d7-7fcf-483c-b1da-a5bb00b8512e)
Points: 100
HasGoldStatus: True
MemberSince: 1/1/2012 12:00:00 AM (Utc)
CreditRating: Good
AverageRating: 42.4242
Orders:
Order Id: e6680e30-5b3b-4efa-b017-a5bb00b85133
Order Id: b03858e7-8c36-4555-8878-a5bb00b85134
The orders were ordered by:
John Doe (10b2a3d7-7fcf-483c-b1da-a5bb00b8512e)
Points: 100
HasGoldStatus: True
MemberSince: 1/1/2012 12:00:00 AM (Utc)
CreditRating: Good
AverageRating: 42.4242
Orders:
Order Id: e6680e30-5b3b-4efa-b017-a5bb00b85133
Order Id: b03858e7-8c36-4555-8878-a5bb00b85134
John Doe (10b2a3d7-7fcf-483c-b1da-a5bb00b8512e)
Points: 100
HasGoldStatus: True
MemberSince: 1/1/2012 12:00:00 AM (Utc)
CreditRating: Good
AverageRating: 42.4242
Orders:
Order Id: e6680e30-5b3b-4efa-b017-a5bb00b85133
Order Id: b03858e7-8c36-4555-8878-a5bb00b85134
Press <ENTER> to exit...
ここで、アプリケーションを確認します。デフォルトはNoneであり、エンティティとエンティティ間の関係を考慮して、各エンティティとそのデータベース内の各関係の適切なカスケードを決定する必要があることに注意してください。