2011-01-21 21 views
7

Nhibernate ile garip bir davranış yaşıyorum. Sorun, nhibernate'in bir varlığı silmeden önce bir güncelleştirme gerçekleştirmesidir. Kategori sınıfım ve Ürün sınıfım var. Kategori ürün bir çanta vardır. Ben Kategori gelen bir ürün kaldırdığınızda, nhibernate yapar aşağıdadır:NHibernate, silme işlemini silmeden önce günceller mi?

  • Ben koleksiyonu
  • Bu veritabanından ürün varlık siler kaldırıldı ürün varlık günceller.

İşte Burada haritalayan

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

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

var İşte sonuç:

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 

herkes bu garip davranışları açıklayabilir?

Teşekkürler.

cevap

12

Kategorisinde Ürünler çantanız için tanımınızda tersi olarak tersi değiştirin. Yanlış olarak tersi ayarlamak, NHibernate'in, Kategori nesnelerinin ilişkideki anahtarın sahibi olduğunu bildirir.

Ürünler koleksiyonunda ters olarak ayarlanmış ters olarak, NHibernate, Kategoriyi ilişkinin sahibi olarak görür. Bu nedenle, Ürün koleksiyonu değiştiğinde, Ürünü Kategoriden kaldırmak için güncelleme ifadesini yayınlar. Daha sonra silme, Ürün silindiği için ortaya çıkar.

+0

Teşekkürler, postanız çok yardımcı oldu :) – Davita

0

DÜZENLEME: Üzgünüm, kod tarafından kafam karıştı; Ps çok açıklayıcı bir özellik değildir. Bu durumda olan şey, Ürünü silme biçiminiz yüzünden (Kategori'deki koleksiyondan çıkarılarak ve daha sonra da Kategoriyi kaydederek), NHibernate ilk olarak Ürünün Kategorisinden referansı kaldırmasıdır, çünkü bu Ürün no daha uzun kategoriye aittir (bu, nesneler ve tablolar arasındaki önemli bir çeviri; OOP'da, içerdiği nesne tarafından referans tutulurken, SQL'de içerilen nesne tarafından tutulur). Şimdi kayıt herhangi bir Kategoriye ait değil; yetim kaldı ve NHibernate'e çağlayan davranışında yetim referansları temizlemesini söylediniz, bu yüzden silme işlemini gerçekleştiriyor.

sadece tek bir SQL deyimi ile yapmak istiyorsanız

, şunu deneyin:

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

Merhaba keith, cevap için teşekkürler. Haklısınız, ama bu isteme göre, bir kategoriyi silmiyorum, sadece bir ürünü kategoriden kaldırıyorum. Yani bu işlem referansları ayırmayı gerektirmiyor ve benim durumumda bu hiç de gerekli değil. – Davita

-2

Bu davranış bana normal görünüyor. NHibernate ile çok az deneyimim var, ama bir kaydı silmek için, silmek istediğiniz kaydı temsil eden nesnenin içinden geçerek, genellikle ISession.Delete yöntemini çağırdığınızı düşünüyorum.

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

Ya da daha açık olmak: Senin durumunda

aşağıdakileri yapmanız mümkün olabilir

Kodunuz silinmesinin bir dolambaçlı yol ortaya çıktığını gözlemledik
// find the product that I want to delete 
var product = c1.Ps[0]; 

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

Ürün kaydı. Kodunuz ürünü açıkça silmiyor, Ürün kaydının o kategori kaydına aykırıdır. Bu yüzden NHibernate güncellemeyi yapıyor.

Kategori sınıfınızda, ilişkinin "cascade" özniteliğini aşağıdaki gibi ürün sınıfı olarak tanımladığınızı unutmayın: cascade="all-delete-orphan". Güncelleme bildiriminiz Ürün kaydının yetim kalmasına neden olduğundan, NHibernate muhtemelen Kaskad ayarınıza göre Ürün kaydının silinmesi gerektiğini ve dolayısıyla silme ifadesini yürütmeye karar verdiğinin farzedildiğini kabul eder.

İlgili konular