2009-08-24 40 views

回答

27

如果使用延遲加載,則Load僅創建一個代理。

session.Delete(session.Load(type, id)); 

使用NH 2.1,您可以使用HQL。不知道它是如何真正的樣子,但這樣的事情:注意,這是受到SQL注入 - 如果可能的話使用參數化查詢與替代的setParameter()

session.Delete(string.Format("from {0} where id = {1}", type, id)); 

編輯:

對於加載,您不需要知道Id列的名稱。

如果你需要知道的話,你可以通過NH元獲得它:

sessionFactory.GetClassMetadata(type).IdentifierPropertyName 

另一個編輯。

session.Delete()被實例化實體

當執行Session.delete(),NH反正加載的實體。起初我不喜歡它。然後我意識到了這些優點。如果實體是使用繼承,集合或「任何」引用的複雜結構的一部分,它實際上更高效。

舉例來說,如果類AB無論從Base繼承,它不會嘗試刪除表B數據時的實際實體是A類型。如果不加載實際的物體,這是不可能的。當存在許多繼承類型時,這也是非常重要的,這些繼承類型每個都包含許多附加表。

當您收集了Base s時,會發生同樣的情況,這些情況恰好是A的所有實例。當將內容加載到內存中時,NH知道它不需要刪除任何B-stuff。

如果實體AB s,它包含C S(等)的集合,它不會嘗試刪除任何C■當的B S中的集合爲空。這隻有在閱讀收藏時纔有可能。當C很複雜時,這一點尤其重要,聚合更多的表格等等。

結構越複雜,動態性越高,加載實際數據的效率就越高,而不是「盲目」地刪除它。

HQL刪除有缺陷

HQL刪除不數據加載到存儲器中。但是HQL刪除不是那麼聰明。他們基本上將實體名稱轉換爲相應的表名並將其從數據庫中刪除。此外,它還會刪除一些彙總的收集數據。

在簡單的結構中,這可能效果良好且高效。在複雜的結構中,並非所有東西都被刪除,導致違反約束或「數據庫內存泄漏」。

結論

我也試圖與NH優化刪除。在大多數情況下,我放棄了,因爲NH仍然更聰明,它「只是有效」,通常足夠快。我寫的最複雜的刪除算法之一是分析NH映射定義並從中建立刪除語句。而且 - 毫不奇怪 - 在刪除之前,如果不從數據庫中讀取數據,這是不可能的。 (我只是減少它只加載主鍵。)

+0

好的,但我不能像原樣使用此代碼,因爲它假定我知道Id列的名稱,我不知道。是否有可能給定實際的實體CLR類型,找到Id列的名稱?畢竟它在映射中。然後,在獲得Id列的名稱後,我可以執行HQL。謝謝 – mark 2009-08-24 20:05:10

+1

請參閱我的附加說明。 – 2009-08-24 20:41:00

+0

幾乎在那裏,但仍然存在問題。一些實體在其映射中定義實體名稱,但不是全部。實體類型總是已知的。問題是GetClassMetadata在其映射中給定定義實體名稱的實體的類型時返回null。所以,當調用sessionFactory.GetClassMetadata(type)的時候我得到了null。我是什麼做的?謝謝。 – mark 2009-08-24 21:06:13