2011-01-21 95 views
7

我與nhibernate有一個奇怪的行爲。問題是 nhibernate在刪除實體之前執行更新。 我有一個Category類和一個Product類。類別有一袋 產品。當我從類別中刪除產品,NHibernate的做了 如下:NHibernate在刪除它之前更新行?

  • 它更新這是我從收集
  • 它從數據庫中刪除產品實體去除產品實體。

這裏的映射

<class name="Category"> 
    <id name="Id"> 
     <generator class="hilo" /> 
    </id> 
    <property name="Name" lazy="false" length="20" /> 

    <bag name="Products" cascade="all-delete-orphan" lazy="false" 
inverse="false"> 
     <key column="CategoryId" /> 
     <one-to-many class="Product" /> 
    </bag> 
    </class> 

    <class name="Product"> 
    <id name="Id"> 
     <generator class="hilo" /> 
    </id> 
    <property name="Name" lazy="false" /> 
    <property name="Discontinued" lazy="false" /> 
    <property name="Price" lazy="false" /> 
    <many-to-one name="Category" 
      class="Category" 
      column="CategoryId" 
      cascade="none" /> 
    </class> 

下面的代碼

using (var session = NHibernateHelper.OpenSession()) 
    using (var transaction = session.BeginTransaction()) 
    { 
     var c1 = session.Load<Category>(32768); 
     c1.Ps.RemoveAt(0); 

     session.SaveOrUpdate(c1); 
     transaction.Commit(); 
    } 

和這裏的結果:

exec sp_executesql N'UPDATE Product SET CategoryId = null WHERE 
CategoryId = @p0 AND Id = @p1',N'@p0 int,@p1 int',@p0=32768,@p1=65537 
go 

exec sp_executesql N'DELETE FROM Product WHERE Id = @p0',N'@p0 
int',@p0=65537 
go 

任何人都可以解釋這種奇怪的行爲?

謝謝。

回答

12

將您的產品包的定義更改爲類別上的反比例。將inverse設置爲false可以告訴NHibernate,Category對象是關係關鍵字的所有者。

當Products集合中的inverse設置爲false時,NHibernate將Category看作關係的所有者。因此,當產品集合發生更改時,它會發布更新聲明以從類別中刪除產品。然後刪除發生,因爲產品已被刪除。

+0

謝謝,你的文章非常有幫助:) – Davita 2011-01-22 13:48:44

0

編輯:對不起,得到了由代碼混淆; Ps不是一個非常具有描述性的屬性。在這種情況下發生的事情是,由於您刪除產品的方式(通過從類別集合中刪除它,然後保存類別),NHibernate首先從產品中刪除對類別的引用,因爲產品no更長的屬於Category(這是對象和表之間的關鍵轉換;在OOP中,引用由包含對象保存,而在SQL中則由包含對象保存)。現在該記錄不屬於任何類別;它是孤立的,並且你告訴NHibernate在它的級聯行爲中清除孤立的引用,所以它執行刪除操作。

如果你想只用一個SQL語句來做到這一點,試試這個:

using (var session = NHibernateHelper.OpenSession()) 
using (var transaction = session.BeginTransaction()) 
{ 
    var c1 = session.Load<Category>(32768); 
    var toDelete = c1.Ps[0]; 
    c1.Ps.RemoveAt(0); 

    session.Delete(toDelete); 
    transaction.Commit(); 
    //you shouldn't need to update the c1 object 
} 
+0

嗨基思,謝謝你的回覆。你是對的,但在這個估計中,我沒有刪除一個類別,我只是從類別中刪除了一個產品。所以這個操作不需要分開引用,在我的情況下,這根本不是必需的。 – Davita 2011-01-21 22:41:37

-2

這種行爲看起來正常的我。我對NHibernate幾乎沒有經驗,但爲了刪除一條記錄,我相信你通常會調用ISession.Delete方法,傳入表示要刪除的記錄的對象。

在你的情況,你也許可以做到以下幾點:

// delete a product 
session.Delete(c1.Ps[0]); 

或者,更清晰:

// find the product that I want to delete 
var product = c1.Ps[0]; 

// now delete it 
session.Delete(product); 

您的代碼似乎正在刪除的環島路產品記錄。您的代碼並未明確刪除產品,而是將產品記錄與該類別記錄分開。這就是爲什麼NHibernate正在進行更新。在您的範疇類,你已經定義了關係的「級聯」屬性商品類爲以下

注意:cascade="all-delete-orphan"。因爲你的更新語句會導致產品記錄孤立,所以NHibernate可能會根據你的級聯設置認識到產品記錄應該被刪除,所以我認爲這就是它決定執行刪除語句的原因。

相關問題