2009-04-27 10 views
8

मैं nHibernate के लिए नया हूं, और वेब एप्लिकेशन फॉर्म पोस्ट से अलग ऑब्जेक्ट्स को अपडेट करने के लिए उचित तरीके से अपना सिर प्राप्त करने का प्रयास कर रहा हूं। , (हम ASP.NET MVC का उपयोग कर रहे)एएसपीनेट पोस्ट एक्शन विधि से निबर्ननेट इकाई को अपडेट करने का सही तरीका क्या है?

वस्तु मैं अद्यतन करने के लिए (अन्य बातों के अलावा) शामिल हैं बच्चे वस्तुओं का एक IList कोशिश कर रहा हूँ कुछ इस तरह से मैप किया:

<bag name="PlannedSlices" inverse="true" cascade="all-delete-orphan"> 
     <key column="JobNumber" /> 
     <one-to-many class="SliceClass" /> 
</bag> 

हम व्यवस्था की है हमारे MVC संपादित दृश्य प्रपत्र इसलिए जब यह वापस पोस्ट किया जाता है, हमारे कार्रवाई विधि बजे वस्तु पारित कर दिया है कि (सूची <> बच्चे मदों की incluing। हम राउंड ट्रिप सभी इकाई आईडी सही ढंग से फ़ॉर्म के माध्यम से।

हमारी अनुभवहीन पर प्रयास पोस्ट एक्शन विधि एक सत्र करता है .aveOrUpdate (parentObject), parentObject के साथ जिसे डिफ़ॉल्ट रूप से व्यू फ़ॉर्म से स्क्रैप किया गया है lbinder।

यह निम्न परिदृश्यों में से किसी के लिए ठीक काम करने के लिए लगता है:

  • एक नया पैरेंट ऑब्जेक्ट
  • नए बच्चे को बनाना, संशोधित माता पिता के गुण
  • जोड़ना वस्तुओं
  • में संशोधन मौजूदा बच्चे वस्तुओं (NHibernate लॉग को देखते हुए, मैं इसे सही ढंग से स्थापित कर सकता हूं यदि ऑब्जेक्ट्स नए हैं या मौजूदा हैं, और उचित अद्यतन या INSERT जारी कर रहे हैं)

जो परिदृश्य विफल रहता है वह है: - बाल वस्तुओं को हटाना - यानी यदि वे IList में नहीं हैं, तो वे डेटाबेस से हटा नहीं पाए जाते हैं। कोई अपवाद या कुछ भी नहीं है, वे सिर्फ हटाए नहीं जाते हैं।

मेरी समझ यह है कि ऐसा इसलिए है क्योंकि जादू जो nHibernate करता है वह बच्चों की एक सूची बनाने के लिए करता है जिसे हटाने की आवश्यकता होती है, अलग-अलग उदाहरणों के साथ काम नहीं करती है।

मैं इस प्रकार की एक्शन विधि को nHibernate (यानी एक मॉडल-बाइंडर ऑब्जेक्ट का उपयोग एक पृथक nHibernate उदाहरण के रूप में उपयोग करना) के बारे में एक साधारण उदाहरण नहीं ढूंढ पाया है - एमएस ईएफ (उदाहरण के लिए http://stephenwalther.com/blog/archive/2009/02/27/chapter-5-understanding-models.aspx) पर आधारित उदाहरण मॉडल-बाउंड ऑब्जेक्ट से बदले गए गुणों को दोबारा लोड किए गए इकाई उदाहरण में प्रतिलिपि बनाने के लिए 'ApplyPropertyChanges' विधि का उपयोग करने लगते हैं।

तो, इसके बाद, सवाल बहुत आसान है - अगर मेरे पास मॉडल बाइंडर है तो मुझे एक नई वस्तु दें जिसमें बाल वस्तुओं का संग्रह शामिल है, मुझे इसे nHibernate के माध्यम से कैसे अपडेट करना चाहिए, (जहां 'अपडेट' संभवतः हटाने में शामिल है बच्चों का)?

उत्तर

4

यहां एक उदाहरण है जो मुझे लगता है कि आप क्या करने की कोशिश कर रहे हैं। मुझे बताएं कि क्या मैंने गलत समझा है कि आप क्या करने की कोशिश कर रहे हैं।

निम्नलिखित "डोमेन" वर्गों को देखते हुए:

public class Person 
{ 
    private IList<Pet> pets; 

    protected Person() 
    { } 

    public Person(string name) 
    { 
     Name = name; 
     pets = new List<Pet>(); 
    } 

    public virtual Guid Id { get; set; } 
    public virtual string Name { get; set; } 
    public virtual IEnumerable<Pet> Pets 
    { 
     get { return pets; } 
    } 

    public virtual void AddPet(Pet pet) 
    { 
     pets.Add(pet); 
    } 

    public virtual void RemovePet(Pet pet) 
    { 
     pets.Remove(pet); 
    } 
} 

public class Pet 
{ 
    protected Pet() 
    { } 

    public Pet(string name) 
    { 
     Name = name; 
    } 

    public virtual Guid Id { get; set; } 
    public virtual string Name { get; set; } 
} 
निम्नलिखित मानचित्रण के साथ

:

public class PersonMap : ClassMap<Person> 
    { 
     public PersonMap() 
     { 
      LazyLoad(); 
      Id(x => x.Id).GeneratedBy.GuidComb(); 
      Map(x => x.Name); 
      HasMany(x => x.Pets) 
        .Cascade.AllDeleteOrphan() 
        .Access.AsLowerCaseField() 
        .SetAttribute("lazy", "false"); 
     } 
    } 

    public class PetMap : ClassMap<Pet> 
    { 
     public PetMap() 
     { 
      Id(x => x.Id).GeneratedBy.GuidComb(); 
      Map(x => x.Name); 
     } 
    } 

इस परीक्षा:

[Test] 
    public void CanDeleteChildren() 
    { 
     Person person = new Person("joe"); 

     Pet dog = new Pet("dog"); 
     Pet cat = new Pet("cat"); 

     person.AddPet(dog); 
     person.AddPet(cat); 

     Repository.Save(person); 

     UnitOfWork.Commit(); 

     CreateSession(); 
     UnitOfWork.BeginTransaction(); 

     Person retrievedPerson = Repository.Get<Person>(person.Id); 
     Repository.Evict(retrievedPerson); 

     retrievedPerson.Name = "Evicted"; 

     Assert.AreEqual(2, retrievedPerson.Pets.Count()); 
     retrievedPerson.RemovePet(retrievedPerson.Pets.First()); 

     Assert.AreEqual(1, retrievedPerson.Pets.Count()); 

     Repository.Save(retrievedPerson); 

     UnitOfWork.Commit(); 

     CreateSession(); 
     UnitOfWork.BeginTransaction(); 

     retrievedPerson = Repository.Get<Person>(person.Id); 
     Assert.AreEqual(1, retrievedPerson.Pets.Count()); 
    } 

रन और निम्नलिखित एसक्यूएल उत्पन्न करता है:

DeletingChildrenOfEvictedObject.CanDeleteChildren: उत्तीर्ण एनएचबीरनेट: [व्यक्ति] (नाम, आईडी) मूल्यों (@ पी 0, @ पी 1) में प्रवेश करें; @ p0 = 'joe', @ p1 = 'cd123fc8-6163-42a5-aeeb-9bf801013ab2'

NHibernate: [पालतू] (नाम, आईडी) VALUES (@ p0, @ p1) में प्रवेश करें; @ पी 0 = 'कुत्ता', @ पी 1 = '464e59c7-74d0-4317-9c22-9bf801013abb'

एनएचबर्ननेट: [पालतू] (नाम, आईडी) मूल्यों (@ पी 0, @ पी 1) में प्रवेश करें; @ P0 = 'बिल्ली', @ p1 = '010c2fd9-59c4-4e66-94fb-9bf801013abb'

NHibernate: अद्यतन [पालतू] सेट Person_id = @ p0 कहां आईडी = @ p1; @ P0 = 'cd123fc8-6163-42a5-aeeb-9bf801013ab2', @ p1 = '464e59c7-74d0-4317-9c22-9bf801013abb'

NHibernate: अद्यतन [पालतू] सेट Person_id = @ p0 कहां आईडी = @ p1; @ P0 = 'cd123fc8-6163-42a5-aeeb-9bf801013ab2', @ p1 = '010c2fd9-59c4-4e66-94fb-9bf801013abb'

NHibernate: person0_.Id Id5_0_, Name5_0_ रूप person0_.Name [व्यक्ति से के रूप में चयन ] person0_ कहां [email protected]; @ P0 = 'cd123fc8-6163-42a5-aeeb-9bf801013ab2'

NHibernate: pets0_.Person_id Person3_1_, से Id1_ रूप pets0_.Id, Id6_0_ रूप pets0_.Id, pets0_.Name Name6_0_ के रूप में [पालतू] pets0_ जहां के रूप में चयन [email protected]; @ p0 = 'cd123fc8-6163-42a5-aeeb-9bf801013ab2'

एनएचबेर्नेट: अद्यतन [व्यक्ति] एसईटी नाम = @ पी 0 WHERE आईडी = @ पी 1; @ p0 = 'evicted', @ p1 = 'cd123fc8-6163-42a5-aeeb-9bf801013ab2'

NHibernate: अद्यतन [पालतू] SET नाम = @ p0 WHERE आईडी = @ p1; @ p0 = 'dog', @ p1 = '464e59c7-74d0-4317-9c22-9bf801013abb' NHibernate: अद्यतन [पालतू] SET Person_id = शून्य जहां Person_id = @ p0 और id = @ p1; @ P0 = 'cd123fc8-6163-42a5-aeeb-9bf801013ab2', @ p1 = '010c2fd9-59c4-4e66-94fb-9bf801013abb'

NHibernate: [पालतू] से हटाएँ कहां आईडी = @ p0; @ P0 = '010c2fd9-59c4-4e66-94fb-9bf801013abb'

NHibernate: Id5_0_, से Name5_0_ रूप person0_.Name [व्यक्ति] person0_ कहां [email protected] रूप person0_.Id का चयन करें; @ P0 = 'cd123fc8-6163-42a5-aeeb-9bf801013ab2'

NHibernate: pets0_.Person_id Person3_1_, से Id1_ रूप pets0_.Id, Id6_0_ रूप pets0_.Id, pets0_.Name Name6_0_ के रूप में [पालतू] pets0_ जहां के रूप में चयन [email protected]; @ P0 = 'cd123fc8-6163-42a5-aeeb-9bf801013ab2'

नोट [पालतू] से हटाएँ ...

तो

, क्या आप ऐसा करने में सक्षम होने की जरूरत है हाथ nhibernate एक व्यक्ति वस्तु (में है यह उदाहरण) संशोधित संग्रह के साथ और यह निर्धारित करने में सक्षम होना चाहिए कि क्या हटाना है। सुनिश्चित करें कि आपके पास Cascade.AllDeleteOrphan() विशेषता सेट है।

+0

इसके लिए बहुत बहुत धन्यवाद - वहां बहुत सारे काम हैं! दुर्भाग्यवश, जिस बिट के साथ मैं संघर्ष कर रहा हूं वह यह है कि मेरे पास दूसरे सत्र/लेनदेन (यानी मेरा पोस्ट) में 'व्यक्ति' वस्तु है जो एक पूरी तरह से नई वस्तु है जिसे मॉडलबिंडर द्वारा एक पुनर्प्राप्त वस्तु के बजाय बनाया गया था, जिसमें एक है कुछ फ़ील्ड संशोधित हुए और इसमें कुछ 'डिलीट बच्चे' कॉल किए गए। मुझे लगता है कि मैं जो खोज रहा हूं वह उस नए ऑब्जेक्ट को लेने और पुनर्प्राप्त ऑब्जेक्ट में इसके परिवर्तन लागू करने का एक तरीका है, ताकि एनएच आवश्यक एसक्यूएल को काम कर सके। शायद यह अस्तित्व में नहीं है। –

+1

जिस तरह से मैं उस स्थिति से निपटने का प्रयास करता हूं वह मॉडल प्रदाता द्वारा प्रस्तुत प्रस्तुति मॉडल ऑब्जेक्ट के रूप में बनाई गई नई वस्तु का इलाज कर रहा है। आपको अभी भी ऑब्जेक्ट को पुनर्प्राप्त करने की आवश्यकता होगी (या किसी भी तरह से "जारी" वर्ग का उदाहरण बनाएं) जिसे आप अपडेट करना चाहते हैं और उस ऑब्जेक्ट पर उन अपडेट को लागू करना चाहते हैं। फिर आप उस ऑब्जेक्ट को NHibernate में सहेज सकते हैं। क्या इसका कोई मतलब है? –

+0

तो आप 'प्रस्तुति (यानी POST)' ऑब्जेक्ट के गुणों के साथ 'पुनर्प्राप्त' ऑब्जेक्ट के गुणों को ओवरराइट करते हैं, तो आप 'मैन्युअल' (यानी संपत्ति-दर-संपत्ति, लूप के साथ या बाल संग्रह के लिए जो भी) करेंगे, तो 'पुनर्प्राप्त' ऑब्जेक्ट के गुणों को ओवरराइट करेंगे? और मैन्युअल रूप से आवश्यक बाल हटावट की गणना? मैं उम्मीद कर रहा था की तुलना में थोड़ा और काम (और रखरखाव!) लगता है। मॉडल-बाइंडर के साथ परेशान करने के लिए मुश्किल से लगता है, वास्तव में, जैसे कि मुझे एक समय में फ़ील्ड को संभालना होगा, मैं उन्हें फॉर्म प्रतिक्रिया से सीधे खींच सकता हूं। फ़िर भी सहायता के लिए धन्यवाद। –

1

रॉब के जवाब ने मुझे 'नए सत्र में मौजूदा आइटम को लोड करने और फिर' दृष्टिकोण को मर्ज करने 'पर अधिक बारीकी से देखने के लिए आश्वस्त किया, और निश्चित रूप से आईएसशन है। मर्ज, जो वास्तव में वही करता है जो मैं चाहता था, जो लेना है एक ताजा वस्तु और इसे अपने पूर्ववर्ती के साथ विलय करें जिसे अभी दूसरे सत्र में पुनः लोड किया गया है।

तो मुझे लगता है कि मैंने जो प्रश्न पूछने की कोशिश की है, उसका जवाब है "मौजूदा इकाई को फिर से लोड करें और फिर नई इकाई के साथ 'ISession.Merge' को कॉल करें।"

संबंधित मुद्दे

 संबंधित मुद्दे