NHibernate-カスケード
この章では、カスケード機能の使用方法について説明します。アイテムのセットまたはコレクション、または顧客と注文などの2つのクラス間の関係があり、外部キー関係がある場合。デフォルトで顧客を削除した場合、NHibernateは子オブジェクトに対して何も行わないため、その顧客に属するものは、注文を孤立させる可能性があります。
また、外部キー制約に違反している可能性があるため、カスケードの概念を使用できます。
デフォルトでは、NHibernateは操作を子オブジェクトにカスケードしません。
これは、デフォルトの配送先住所を持つ顧客などの関係を築くことができ、配送先住所が多くの異なる顧客と共有されるためです。
したがって、他の顧客がまだそれを参照しているため、必ずしもその関係をカスケードする必要はありません。
したがって、カスケードの全体的な概念は、NHibernateにその子エンティティを処理する方法を指示することです。
カスケードにはさまざまなオプションがあり、次のとおりです。
none −これはデフォルトであり、カスケードがないことを意味します。
all −これは、保存、更新、および削除をカスケードします。
save-update −カスケード、保存、更新します。
delete −削除をカスケードします。
all-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であり、エンティティとそれらの間の関係を考慮して、各エンティティとそのデータベース内の各関係に適切なカスケードを決定する必要があることを忘れないでください。