2009-04-29 60 views
1

我有一個多對一的對象ProductSupplier之間的關係。我需要刪除Supplier而不刪除屬於它的ProductNHibernate多對一關係刪除父親只有

這裏是類的簡化版本:

public class Supplier { 
    public virtual IList<Product> Products { get; protected set; } 
} 

public class Product { 
    // Product belongs to a Category but Supplier is optional 
    public virtual Supplier Supplier { get; set; } 
    public virtual Category Category { get; set; } 
} 

我使用FluentNHibernate,但這裏有它產生的映射:

<bag name="Products" cascade="save-update" inverse="true"> 
     <key column="SupplierID" /> 
     <one-to-many class="Me.Product, Me, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
</bag> 

<many-to-one name="Supplier" column="SupplierID" /> 

這將創建產品表的外鍵,所以當我試圖對供應商進行直接刪除時,我得到一個外鍵約束錯誤。我嘗試將cascade改爲'all',希望它只能刪除關係,但它刪除了所有產品及其他關聯的對象。

我現在看到的解決此問題的唯一方法是迭代供應商的產品集合,並將供應商屬性設置爲空。有沒有辦法通過映射來實現這種行爲?

+0

數據庫是自動生成的,所以沒有。 – roryf 2009-04-29 10:49:37

+0

此外,我會有幻影SupplierID值沒有關係 – roryf 2009-04-29 10:50:23

回答

2

映射屬性僅在實體實際加載時以及未通過HQL查詢時才生效。例如,如果您指定Cascade=ALL,如果刪除供應商的查詢爲"delete from Supplier where id=:id",則可能會得到相同的FK約束失敗,因爲hql不會觸發(編程式)級聯。

看來,產品是關係的擁有方,這是很好的。我認爲你有兩個選擇:

  • 代碼對供應商的一些方法,通過所有的產品迭代,並設置了產品的供應商爲null,並刪除任何供應商
  • 發出供應商刪除之前前使用此方法,使確保您的DAO設置產品的供應商爲null

例子:

public int Delete(Supplier s) { 
    return Session.CreateQuery("udpate Product set Supplier = null where Supplier = :supplier") 
     .SetParameter("supplier", s) 
     .ExecuteUpdate(); 
} 
+0

沒有想過做它作爲數據訪問層內的查詢,這是完美的! – roryf 2009-04-29 14:11:40

0

千萬不要這麼做。

您的模型中隱式或顯式斷言所有產品都有供應商。外鍵在那裏執行這個條件。在保持產品違反您的模型的情況下移除供應商,並可能導致大部分依賴於此的代碼都失敗。

您可以做的一件事是,您已經發現:對於擁有此供應商的每個產品,您都可以將產品的供應商設置爲空。這不會違反你的條件,但這與「我們不知道這個產品的供應商是誰」並且可能導致代碼失敗一樣。

你爲什麼要這樣做?

相關問題