NHibernate - Kaskaden

In diesem Kapitel wird die Verwendung der Kaskadenfunktion beschrieben. Wenn Sie ein Set oder eine Sammlung von Artikeln oder eine Beziehung zwischen zwei Klassen wie unserem Kunden und unserer Bestellung haben und eine Fremdschlüsselbeziehung haben. Wenn wir den Kunden standardmäßig löschen, macht NHibernate nichts mit den untergeordneten Objekten, also mit denen, die zu diesem Kunden gehören, und wir könnten Orphan-Orders sein.

  • Wir könnten auch gegen Fremdschlüsseleinschränkungen verstoßen, sodass wir den Begriff der Kaskaden verwenden können.

  • Standardmäßig kaskadiert NHibernate keine Operationen auf untergeordnete Objekte.

  • Der Grund dafür ist, dass Sie Beziehungen haben können, z. B. wenn ein Kunde eine Standardversandadresse hat und diese Lieferadresse mit vielen verschiedenen Kunden geteilt wird.

  • Sie möchten diese Beziehung also nicht unbedingt kaskadieren, da andere Kunden immer noch darauf verweisen.

  • Die ganze Idee von Kaskaden besteht also darin, NHibernate zu sagen, wie sie mit ihren untergeordneten Entitäten umgehen sollen.

Es gibt verschiedene Optionen für die Kaskadierung:

  • none - Dies ist die Standardeinstellung und bedeutet keine Kaskadierung.

  • all - das Speichern, Aktualisieren und Löschen kaskadieren wird.

  • save-update - Es wird kaskadieren, speichern und aktualisieren.

  • delete - Löschungen werden kaskadiert.

  • all-delete-orphan - Es handelt sich um ein spezielles Element, das häufig verwendet wird und mit "Alle außer" identisch ist. Wenn es verwaiste verwaiste Zeilen findet, werden auch diese gelöscht.

Sie können den Standard in Ihrem angeben hbm.xml Datei, sodass Sie eine Standardkaskade für dieses Hibernate-Zuordnungselement bereitstellen oder sie auch für bestimmte Sammlungen und Beziehungen wie das Viele-zu-Eins-Element angeben können.

Schauen wir uns einfache Beispielkaskaden an, beheben wir das Problem im Programm, wo wir das Speichern manuell in die Bestellungen kaskadieren müssen, wie im folgenden Code gezeigt.

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(); 
}

Im obigen Code-Snippet können Sie sehen, dass wir alle Bestellungen für den Kunden manuell speichern. Entfernen wir nun den manuellen Kaskadencode, in dem alle Bestellungen gespeichert sind.

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(); 
}

Wir müssen die Kaskadenoption in angeben 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>
  • Jetzt gehören Bestellungen vollständig dem Kunden. Wenn die Kunden aus der Datenbank gelöscht würden, würde unsere Anwendung hier alle diese Bestellungen löschen wollen, einschließlich aller möglicherweise verwaisten.

  • Am Ende wird ein Löschvorgang ausgeführt. Auf diese Weise wird "Aus Auftragstabelle löschen" angezeigt, wobei die Kunden-ID dem Kunden entspricht, den Sie löschen.

  • Sie können diese Löschvorgänge also tatsächlich kaskadieren. Also mit demAllEs wird gespeichert, aktualisiert und gelöscht.

Wenn Sie diese Anwendung ausführen, wird die folgende Ausgabe angezeigt.

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...

Wie Sie sehen, haben wir den Code aus dem manuell kaskadierten Programm gelöscht und unsere Anwendung funktioniert noch.

Abhängig von Ihrer Beziehung möchten Sie diese möglicherweise kaskadieren. Schauen wir uns nun eine andere Kaskadenbeziehung an. Lass uns zu ... gehenOrder.hbm.xml Datei und wir können diese Viele-zu-Eins-Beziehung kaskadieren.

<?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>

Wenn wir also eine neue Bestellung erstellen und ein neuer Kunde damit verbunden ist und wir sagen, diese Bestellung speichern, möchten wir diese möglicherweise kaskadieren. Eine Sache, die wir wahrscheinlich nicht tun möchten, ist, wenn eine Bestellung gelöscht wird, um den entsprechenden Kunden zu löschen.

Hier möchten wir also ein Sicherungsupdate durchführen. Wenn Sie also ein Sicherungsupdate verwenden, werden alle Speicherungen oder Aktualisierungen für diesen Kunden kaskadiert. Wenn wir also einen neuen Kunden bekommen oder den Kunden wechseln, wird dies kaskadieren. Wenn es sich um ein Löschen handelt, wird es nicht aus der Datenbank gelöscht.

Wenn Sie unsere Anwendung erneut ausführen, funktioniert immer noch alles wie erwartet.

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...

Jetzt sollten Sie sich Ihre Anwendung ansehen, sich daran erinnern, dass die Standardeinstellung Keine ist, und Sie müssen über Ihre Entitäten und Ihre Beziehungen zwischen ihnen nachdenken, um die geeigneten Kaskaden für jede Ihrer Entitäten sowie für jede Ihrer Beziehungen in dieser Datenbank zu bestimmen.