2010-02-19 53 views
9

我有一個名爲「Customer」的對象,它將在其他表中用作外鍵。如何查找是否可以刪除引用的對象?

的問題是,我想知道,如果「客戶」可以被刪除(即,它不被任何其他表引用)。

這可能與Nhibernate?

+0

你說'Customer'在「其他表」中所引用。複數的意圖是什麼?即,是從多個其他實體類引用的客戶。 (答案影響可能的解決方案。) – 2010-02-19 08:21:14

+0

@Jorn,是的,它在很多其他表格中被引用。 – 2010-02-19 09:14:08

回答

5

你問什麼是找到Customer PK值的存在被引用的表FK列英寸 有很多方法,你可以去一下:

  1. 爲kgiannakakis指出,嘗試做刪除,如果拋出一個異常回滾。有效但醜陋,無用。這也要求您在數據庫中設置CASCADE =「RESTRICT」。該解決方案有,你必須嘗試刪除對象來找出你不能

  2. 地圖引用Customer作爲收藏品,然後爲每個集合的實體,如果他們Count > 0則不允許刪除的缺點。這很好,因爲只要映射完成,這對於模式更改是安全的。這也是一個不好的解決方案,因爲必須進行額外的選擇。

  3. 具有執行像bool IsReferenced(Customer cust)查詢的方法。好,因爲你可以有一個你想要的時候使用的單個查詢。不太好,因爲它可能容易因模式和/或域更改而導致錯誤(取決於您將執行的查詢類型:sql/hql/criteria)。

  4. 在類它自與像<property name="IsReferenced" type="long" formula="sql-query that sums the Customer id usage in the referenced tables" />的映射元素A計算的屬性。好,因爲它是一個快速解決方案(至少和你的數據庫一樣快),不需要額外的查詢。不太好,因爲它容易發生模式更改,因此當您更改數據庫時,不要忘記更新此查詢。

  5. 瘋狂溶液:創建模式綁定視圖,使得計算。在需要時對其進行查詢。好,因爲它的模式綁定並且不太容易發生模式更改,這很好,因爲查詢很快,不太好,因爲您仍然需要執行額外的查詢(或者將解決方案4中的視圖結果映射到該映射)。

2,3,4都還不錯,因爲你也可以投射這種行爲,以您的UI(不允許刪除)

個人而言,我會去爲4,3,5與偏好

+1

這是一個很好的答案,很難回答更具體的問題,因爲你的情況細節不是很清楚。對你的簡短回答是「是」。你可以想象在你的數據庫上運行的任何查詢都可以在nHibernate中以某種方式進行(如果你正在使用HQL,則使用HQL)。 – 2010-02-25 23:33:59

1

這是不可能的。假設您的域名模型包含客戶的相關對象,例如地址,訂單等。您應該使用specification pattern

public class CustomerCanBeDeleted 
{ 

    public bool IsSatisfiedBy(Customer customer) 
    { 
     // Check that related objects are null and related collections are empty 
     // Plus any business logic that determines if a Customer can be deleted 
    } 
} 

編輯補充:

也許最簡單的方法是創建一個執行此檢查存儲過程並刪除之前調用它。你可以從NHibernate訪問一個IDbCommand(ISession.Connection.CreateCommand()),這樣這個調用就是數據庫不可知的。

另請參閱對this question的迴應。

0

一個天真的解決方案將使用一個事務。開始一個事務並刪除該對象。異常會通知您該對象無法刪除。無論如何,做一個回滾。

2

在實體和關係中思考而不是表和外鍵,存在以下不同情況:

  • 客戶擁有建立客戶的一部分的一對多關係,例如他的電話號碼。它們也應該通過級聯方式刪除。
  • 客戶有一對多或多對多的關係,這不是客戶的一部分,但他們是客戶知道/可以訪問的。
  • 其他一些實體與客戶有關係。它也可以是任意類型的(它不是數據庫中的外鍵)。例如客戶的訂單。訂單不被客戶所知。這是最難的情況。

據我所知,NHibernate沒有直接的解決方案。有元數據API,它允許您在運行時探索映射定義。恕我直言,這是做錯的方法。

在我看來,業務邏輯的責任是驗證一個實體是否可以刪除或不。 (即使存在確保數據庫完整性的外鍵和約束,它仍然是業務邏輯)。

我們實現了在刪除實體前調用的服務。軟件的其他部分爲某些類型註冊。他們可以否決刪除(例如通過拋出異常)。

例如,訂單系統註冊刪除客戶。如果客戶應該被刪除,訂單系統會搜索該客戶的訂單,並在找到訂單時拋出。

+0

你讓我在業務邏輯中考慮這個問題 – 2010-03-02 10:15:20

4

我想知道是否可以刪除「客戶」(即,它不在任何其他表中引用)。

確定客戶是否可以刪除並不是真正的數據庫責任。這是業務邏輯的一部分。

您要求檢查數據庫上的參照完整性。

在非OOP世界中可以。但是當處理對象時(像你一樣),你最好把邏輯添加到你的對象中(對象有狀態和行爲; DB--只有狀態)。

所以,我會添加一個方法到客戶類,以確定它是否可以刪除或不。這樣你可以正常(單元)測試功能

例如,假設我們有一條規則如果客戶沒有訂單並且未參與論壇,則只能將其刪除。

然後,你將有類似這樣的客戶對象(最簡單可行的情況下):

public class Customer 
{ 
    public virtual ISet<Order> Orders { get; protected set; } 
    public virtual ISet<ForumPost> ForumPosts { get; protected set; } 

    public virtual bool CanBedeleted 
    { 
     get 
     { 
      return Orders.Count == 0 && ForumPosts.Count == 0 
     } 
    } 
} 

這是非常乾淨和簡單的設計,易於使用,測試和不嚴重依賴於NHibernate的或基礎數據庫。

您可以使用它像這樣:

if (myCustomer.CanBeDeleted) 
    session.Delete(mycustomer) 

此外,如果需要,您可以微調NHibernate的刪除相關的訂單和其他協會。


注:當然上面的例子只是最簡單的說明性解決方案。您可能想要制定一條規則part of the validation,在刪除對象時應執行該規則。

+1

你正在通過調用[collection] .Count屬性(至少)2個額外的選擇。另外,形成的單元測試(或不存在的)會通過一個條件。這可以通過應用數據庫約束來保存!它總是一個很好的做法是,後端不依賴於前端業務邏輯數據的完整性 – Jaguar 2010-03-05 11:57:17

+0

您可以通過使用預先抓取或其他方式微調SQL測繪,目的是驗證這個想法。至於'這可以通過應用數據庫約束來保存' - 我提到它也應該是驗證的一部分。 – 2010-03-06 00:41:45

+0

我會爭辯說,檢查數據庫參照完整性是**不是**業務邏輯的一部分 - 我認爲只有當您的程序是數據庫程序時纔是這種情況。 – fostandy 2016-03-29 00:16:17

相關問題