2010-02-16 34 views
5

İki varlıkla (Veli ve Çocuk) arasında ana çocuk ilişkisi var. aşağıdaki gibiKoleksiyondan bir öğenin kaldırılması (NHibernate)

Benim Veli haritalama geçerli:

<class name="Parent" table="Parents"> 
    ... 
    <bag name="Children" cascade="all"> 
     <key column="ParentID"></key> 
     <one-to-many class="Child"></one-to-many> 
    </bag> 
</class> 

aşağıdaki yürütmek istiyorum:

someParent.Children.Remove(someChild); 

Çocuk sınıfı Model, başka ana sınıfına bir referansı vardır. ilişki

relation diagram

gibi Not görünür: Yukarıda bağlantılı olmayan url dolayı özür, ben Bundan dolayı İşaretleme

kullanan URL dizesinde yıldız işareti geçmiş olsun gibi görünüyor olabilir ilişki, yukarıdaki kod çağrıldığında, DELETE sorgusu yerine, Child tablosundan ParentID'yi kaldıran bir UPDATE sorgusu oluşturulur (null olarak ayarlar).

NHibernate'i, Parent.Children koleksiyonundan kaldırıldığında, çocuk kaydını tamamen silmeye zorlamak mümkün mü?

GÜNCELLEME Spencer'ın Çözüm

Çok çekici çözümü @

bu gelecek sınıflarında uygulanacak bir şeydir olarak. Bununla birlikte, oturumlar, depo modelinde (özel durumumda) ele alınma şekline bağlı olarak, uygulamaya bağlı olarak oturum türlerini (CallSessionContext/WebSessionContext) geçmemiz gerektiği için bu imkansızdır.

Jamie'nin Çözüm

Basit ve uygulanması için hızlı, ancak isabet ettik başka yol bloğu @. şöyle Çocuğum varlık arar: entity object

yeni yöntemi kullanarak NHibernate düpedüz tek silme aksine, null TypeId ve parentId ayarı bir güncelleme deyimi oluşturur. Eğer uygulama içinde bir şeyi özlediysem, bu yöntemin ilerlemek için ağrısız olacağını bilmeme izin verin.

@The One-Shot-Delete solution described here, tek bir silme zorlamak için koleksiyonun kaldırılmasıyla ilgili bir fikri özetlemektedir. Ancak yukarıdaki gibi aynı sonuçlar, bir güncelleme beyanı verilir.

//Instantiate new collection and add persisted items 
List<Child> children = new List<Child>(); 
children.AddRange(parent.Children); 

//Find and remove requested items from new collection 
var childrenToRemove = children 
    .Where(c => c.Type.TypeID == 1) 
    .ToList(); 

foreach (var c in childrenToRemove) { children.Remove(m); } 
parent.Children = null; 

//Set persisted collection to new list 
parent.Children = Children; 

Çözüm kazma biraz aldı ama Jamie'nin çözüm bazı ek değişikliklerle geldi. = Ters = true, Cascade tüm

Veli eşlemesi - - Ters = true, Cascade = hepsi silme-yetim

gibi yöntemleri çıkarın

Tip haritalama: Gelecekteki okuyucuların, yukarıda benim sınıf modeline dayalı Jamie'nin çözüm çalışmalarında anlatılmıştır.Bu öksüz öğe başına tek bir silme ifadesi üretiyor, bu yüzden gelecekte ayarlama imkanı var, ancak sonuç başarılı.

cevap

1

bir yöntemle koleksiyona erişimi kontrol RemoveChild yöntemleri.

0

Bunun tam olarak mümkün olduğunu düşünmüyorum, çünkü hazırda bekletmenin yetim olup olmadığını bilmenin hiçbir yolu yoktur. Başka bir sınıfın çocuk sınıfıyla ilişkili olup olmadığını kontrol edebilir, ancak bu durumda DB yapısının farkında olmayacağını varsayabilir. Bununla birlikte, tam olarak şanstan yoksun değilsiniz. IList arabirimini kullanarak oluşturacağınız özel bir ICascadeDeleteChild arabirimiyle birlikte oldukça sorunsuz bir çözüm bulabilirsin. İşte temel adımlar.

  1. IList ve IList < inheirits bir sınıf oluşturun> ve CascadeDeleteList veya bu doğrultuda bir şey diyoruz.
  2. Bu sınıfın içinde özel bir Net listesi oluşturun ve bu listeye çeşitli yöntem çağrılarını proxy yapın.
  3. ICascadeDeleteChild adlı bir Arayüz oluşturun ve ona bir yöntem verin. Delete()
  4. CascadeDeleteListinizin Silme yönteminin altında, silinecek nesnenin türünü kontrol edin. ICascadeDeleteChild türünde ise, o zaman Silme yöntemini çağırın.
  5. ICascadeDeleteChild arabirimini uygulamak için Çocuk sınıfınızı değiştirin.

Bunun bir acı gibi göründüğünü biliyorum ama bu yapıldığında bu arayüzler etrafta dolaşmak için basit olmalı.

RemoveChild(Child child) 
{ 
    Children.Remove(child); 
    child.Parent = null; 
    child.Type.RemoveChild(child); 
} 

Type.RemoveChild benzer görünecektir ancak birbirleri 's çağıran sonsuz bir döngüye koydu için dikkatli olmak gerekir: Yerine IList<Child> ortaya çıkarmak gibi

+0

Bu yolun beni doğru yola soktuğuna inanıyorum, yol blokları şu şekildedir: bunu bir havuz düzeninde ayarlama (yani, bu durumda çocuk Silme yöntemi kendi depo yöntemini çağırır) ve aynı zamanda Bu farklı oturum bağlamları ile (örneğin, CallSessionContext vs WebSessionContext) –