NHibernate - Cascades

在本章中,我们将介绍如何使用Cascade功能.如果您有一组或一组项目或两个类之间的关系,例如我们的客户和订单,并且具有外键关系.如果我们默认删除客户,NHibernate不会对子对象做任何事情,所以那些属于该客户的我们可能是孤儿订单.

  • 我们也可能违反外键约束,所以我们可以使用级联的概念.

  • 默认情况下,NHibernate不会将操作级联到子对象.

  • 这样做的原因是您可以拥有诸如客户具有默认送货地址和送货地址的关系.与许多不同的客户分享.

  • 因此,您不希望因为其他客户仍在提及它而无法级联该关系.

  • 所以级联的整个概念是告诉NHibernate如何处理它的子实体.

级联有不同的选项,如下:

  • none :这是默认值,表示没有级联.

  • 所有 : 这将是级联保存,更新和删除.

  • save-update : 它将级联,保存和更新.

  • 删除 : 它会级联删除.

  • all-delete-orphan : 它是一个经常使用的特殊的,与All Allcept相同,如果它找到Delete-orphan行,它也会删除它们.

您可以在 hbm.xml 文件中指定默认值,这样您就可以在该Hibernate映射元素上提供默认级联,或者您也可以为特定的集合和关系指定它,例如多对一.

让我们看看简单的示例级联,让我们解决程序中的问题,我们必须手动将保存级联到订单,如下所示以下代码.

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等于您要删除的客户.

  • 因此,您可以实际级联这些删除.因此,使用全部,它将执行保存,更新和删除.

现在运行此时应用程序,您将看到以下输出.

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 文件,我们可以级联这种多对一关系.

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

因此,如果我们创建一个新订单并且附加了一个新客户,我们说,保存该订单,我们可能希望级联该订单.但是我们可能不想做的一件事是删除订单以删除相应的客户.

所以在这里,我们希望进行保存更新,所以使用保存更新,它会将任何保存或更新级联到该客户.因此,如果我们得到一个新客户或者如果我们正在改变客户,它将会级联.如果它是删除,它不会从数据库中删除它.

因此,再次运行我们的应用程序,一切仍然按预期工作.

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,你必须考虑你的实体和你的关系在它们之间确定每个实体的适当级联以及该数据库中的每个关系.