2013-03-21 95 views
2

我有兩個實體Password和PasswordHash。密碼包含一組PasswordHashes(這些是具有不同掩碼的哈希)。NHibernate使用Cascade進行刪除操作導致N + 1刪除

當我刪除密碼時,我希望所有關聯的密碼哈希也被刪除。

我不喜歡這樣的映射:

mapping.HasMany(x => x.PasswordHashes) 
      .Cascade 
      .All() 
      .Inverse() 
      .ReferencedBy(x => x.Password); 

我預計將產生的兩個查詢:

DELETE FROM "PasswordHash" WHERE "IdPassword" = :p0 

和明顯

DELETE FROM "Password" WHERE "IdPassword" = :p0 

相反NHibernate的產生的N + 1的查詢像這樣:

DELETE FROM "PasswordHash" WHERE "IdPasswordHash" = :p0 (N) 

DELETE FROM "Password" WHERE "IdPassword" = :p0 (1) 

我怎樣才能改變這種行爲,以更優?

編輯:代碼刪除:

session.Delete(password); 
session.Flush(); 
+1

您可以給出導致N + 1刪除的代碼嗎? – mickfold 2013-03-21 10:18:37

+1

我想這個,你用來執行刪除的代碼,可能是有趣的:http://www.nhforge.org/doc/nh/en/index.html#performance-collections-oneshotdelete – jbl 2013-03-21 12:29:33

+0

刪除HQL兒童(第一次旅行),然後刪除父母?您還使用哪個數據庫供應商? – Rippo 2013-03-21 14:52:13

回答

2

從我的研究,在NHibernate的(3.3)的當前版本中,它看起來是無法刪除的子集用行動一個DELETE聲明如域名對象上的password.hashes.Clear()session.Delete(password)。 NHibernate的文檔指的是one shot deletes,但我還沒有能夠得到這項工作與逆和級聯的單向或雙向一對多關聯的任何組合。

一種替代方法是使用on-delete="cascade",它禁用NHibernate中的級聯功能,並將其留給數據庫以強制執行級聯刪除。更多信息可以在this nh用戶谷歌小組討論中找到。

Rippo在評論部分提到的另一種選擇是使用HQL。您需要兩條語句,因此最好將它們包裝在交易中,即

using (var transaction = session.BeginTransaction() 
{ 
    session.Query("delete from PasswordHash h where h.Password = :password") 
        .SetParameter("password", password) 
        .ExecuteUpdate(); 
    session.Delete(password); 
    transaction.Commit(); 
}