NHibernate - Cascades

Trong chương này, chúng tôi sẽ trình bày cách sử dụng tính năng Cascade. Nếu bạn có một tập hợp hoặc một tập hợp các mặt hàng hoặc mối quan hệ giữa hai lớp như khách hàng và đơn hàng của chúng tôi và có mối quan hệ khóa ngoài. Nếu chúng tôi xóa khách hàng theo mặc định, NHibernate không thực hiện bất kỳ hành động nào đối với các đối tượng con, vì vậy những đối tượng thuộc về khách hàng đó và chúng tôi có thể là đơn đặt hàng mồ côi.

  • Chúng tôi cũng có thể vi phạm các ràng buộc khóa ngoại, vì vậy chúng tôi có thể sử dụng khái niệm về các tầng.

  • Theo mặc định, NHibernate không phân tầng các hoạt động với các đối tượng con.

  • Lý do là bạn có thể có những mối quan hệ như một khách hàng có địa chỉ giao hàng mặc định và địa chỉ giao hàng đó được chia sẻ với nhiều khách hàng khác nhau.

  • Vì vậy, bạn sẽ không muốn kết nối mối quan hệ đó nhất thiết vì những khách hàng khác vẫn đang đề cập đến nó.

  • Vì vậy, toàn bộ khái niệm về thác là để cho NHibernate biết cách xử lý các thực thể con của nó.

Có các tùy chọn khác nhau để xếp tầng, như sau:

  • none - là mặc định và nó có nghĩa là không xếp tầng.

  • all - sẽ lưu, cập nhật và xóa theo tầng.

  • save-update - nó sẽ phân tầng, lưu và cập nhật.

  • delete - nó sẽ xóa theo tầng.

  • all-delete-orphan - nó là một đặc biệt được sử dụng khá thường xuyên và giống với Tất cả Ngoại trừ, nếu nó tìm thấy hàng Xóa-mồ côi, nó cũng sẽ xóa những hàng đó.

Bạn có thể chỉ định giá trị mặc định trong hbm.xml , vì vậy bạn có thể cung cấp một tầng mặc định trên phần tử ánh xạ Hibernate đó hoặc bạn cũng có thể chỉ định nó cho các tập hợp và mối quan hệ cụ thể chẳng hạn như nhiều-một.

Hãy xem xét các tầng ví dụ đơn giản, chúng ta hãy khắc phục sự cố trong chương trình, trong đó chúng ta phải xếp tầng theo cách thủ công lưu vào các đơn đặt hàng như được hiển thị trong đoạn mã sau.

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

Trong đoạn mã trên, bạn có thể thấy rằng chúng tôi đang lưu tất cả các đơn đặt hàng cho khách hàng theo cách thủ công. Bây giờ chúng ta hãy xóa mã xếp tầng thủ công trong đó tất cả các đơn hàng được lưu.

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

Chúng tôi cần chỉ định tùy chọn xếp tầng trong 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>
  • Bây giờ, đơn đặt hàng hoàn toàn thuộc về khách hàng. Vì vậy, nếu khách hàng bị xóa khỏi cơ sở dữ liệu, ứng dụng của chúng tôi ở đây sẽ muốn xóa tất cả các đơn đặt hàng đó, bao gồm bất kỳ đơn hàng nào có thể đã bị bỏ sót.

  • Nó sẽ kết thúc việc xóa. Bằng cách đó, nó sẽ cho biết xóa khỏi bảng đơn đặt hàng, trong đó ID khách hàng bằng với khách hàng mà bạn đang xóa.

  • Vì vậy, bạn thực sự có thể xếp tầng các lần xóa này. Vì vậy, vớiAll, nó sẽ thực hiện lưu, cập nhật và xóa.

Bây giờ khi bạn chạy ứng dụng này, bạn sẽ thấy kết quả sau.

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

Như bạn có thể thấy rằng chúng tôi đã xóa mã khỏi chương trình xếp tầng thủ công và ứng dụng của chúng tôi vẫn đang hoạt động.

Vì vậy, tùy thuộc vào mối quan hệ của bạn, bạn có thể muốn phân chia chúng. Bây giờ, chúng ta hãy xem xét một mối quan hệ khác. Hãy đi đếnOrder.hbm.xml và chúng tôi có thể phân tầng mối quan hệ nhiều-một đó.

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

Vì vậy, nếu chúng tôi tạo một đơn đặt hàng mới và có một khách hàng mới gắn liền với đơn đặt hàng đó và chúng tôi nói, hãy lưu đơn đặt hàng đó, chúng tôi có thể muốn xếp tầng đó. Nhưng có một điều mà chúng tôi có lẽ không muốn làm là nếu một đơn hàng bị xóa sẽ xóa khách hàng tương ứng.

Vì vậy, ở đây, chúng tôi muốn thực hiện cập nhật lưu, do đó, sử dụng cập nhật lưu, nó sẽ phân tầng bất kỳ bản lưu hoặc cập nhật nào cho khách hàng đó. Vì vậy, nếu chúng ta có được một khách hàng mới hoặc nếu chúng ta thay đổi khách hàng, thì điều đó sẽ xảy ra. Nếu đó là một xóa, nó sẽ không xóa nó khỏi cơ sở dữ liệu.

Vì vậy, chạy lại ứng dụng của chúng tôi, mọi thứ vẫn hoạt động như mong đợi.

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

Bây giờ bạn sẽ xem xét ứng dụng của mình, hãy nhớ rằng mặc định là Không có và bạn phải suy nghĩ về các thực thể của mình và các mối quan hệ giữa chúng để xác định các tầng thích hợp cho từng thực thể cũng như từng mối quan hệ của bạn trong cơ sở dữ liệu đó.