2011-01-21 15 views
7

Mam dziwne zachowanie z nhibernate. Problem polega na tym, że nhibernate wykonuje aktualizację przed usunięciem encji. Mam klasę kategorii i klasę produktu. Kategoria ma torbę z produktami . Kiedy usunąć produkt z kategorii, NHibernate robi następujący:NHibernate aktualizuje wiersz przed usunięciem?

  • To aktualizuje jednostkowego produktu którego usuwany z kolekcji
  • Usuwa podmiot produktów z bazy danych.

Tutaj odwzorowania

<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> 

Oto kod

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(); 
    } 

i oto wynik:

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 

Każdy może wyjaśnić to dziwne zachowanie?

Dzięki.

Odpowiedz

12

Zmień odwrotność na true w definicji torebki z produktami w kategorii. Ustawienie odwrotne do false informuje NHibernate, że obiekty kategorii są właścicielem klucza w relacji.

Z odwrotnym ustawieniem na fałsz w kolekcji Produkty, NHibernate widzi kategorię jako właściciela relacji. Kiedy więc zmienia się kolekcja Produktów, wydaje instrukcję aktualizacji, aby usunąć Produkt z Kategorii. Usunięcie nastąpi, ponieważ produkt został usunięty.

+0

Dzięki, twój wpis był bardzo pomocny :) – Davita

0

EDYCJA: Przepraszam, zostałem zagubiony przez kod; Ps nie jest bardzo opisową własnością. W tym przypadku dzieje się tak, że z powodu sposobu, w jaki usuwasz Produkt (usuwając go z kolekcji w Kategorii, a następnie zapisując Kategorię), NHibernate najpierw usuwa odniesienie do Kategorii z Produktu, ponieważ ten Produkt nie dłużej należy do kategorii (jest to kluczowe tłumaczenie między obiektami i tabelami, w OOP odwołanie jest przechowywane przez obiekt zawierający, podczas gdy w SQL jest trzymane przez zawarty obiekt). Teraz rekord nie należy do żadnej kategorii; Zostało osierocone i powiedziałeś NHibernate, aby wyczyścił osierocone odniesienia w swoim kaskadowym zachowaniu, więc wykonuje usuwanie.

Jeśli chcesz to zrobić za pomocą jednego zapytania SQL, spróbuj tego:

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

Cześć, dzięki za odpowiedź. Masz rację, ale w tej wersji nie usuwam kategorii, po prostu usuwam produkt z kategorii. Tak więc ta operacja nie wymaga odrywania referencji iw mojej sytuacji nie jest to wcale wymagane. – Davita

-2

To zachowanie wygląda normalnie do mnie. Mam niewielkie doświadczenie z NHibernate, ale aby usunąć rekord, uważam, że zazwyczaj nazywasz metodę ISession.Delete, przekazując obiekt reprezentujący rekord, który chcesz usunąć.

W twoim przypadku, może być w stanie wykonać następujące czynności:

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

Albo, żeby być bardziej oczywiste:

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

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

Kod wydaje się być przy okrężną drogę Usuwanie Zapis produktu. Twój kod nie usuwa jawnie produktu, a raczej odłącza ten rekord produktu z tym rekordem kategorii. Właśnie dlatego NHibernate robi aktualizację.

Należy zauważyć, że w klasie Kategoria zdefiniowano atrybut "kaskada" relacji z klasą produktu: cascade="all-delete-orphan". Ponieważ instrukcja aktualizacji powoduje, że rekord produktu zostaje osierocony, NHibernate prawdopodobnie rozpoznaje, że rekord produktu powinien zostać usunięty, zgodnie z ustawieniami kaskadowymi, i dlatego zakładam, że właśnie dlatego postanawia wykonać instrukcję usuwania.

Powiązane problemy