[c#] मैं बाल वस्तुओं को सहेजने / डालने की कोशिश से इकाई फ्रेमवर्क को कैसे रोकूं?



4 Answers

लंबी कहानी छोटी: विदेशी कुंजी का उपयोग करें और यह आपके दिन को बचाएगा।

मान लीजिए कि आपके पास स्कूल इकाई और एक सिटी इकाई है, और यह एक से एक रिश्ते है जहां एक शहर में कई स्कूल हैं और एक स्कूल शहर से संबंधित है। और मान लें कि शहर लुकअप टेबल में पहले से मौजूद हैं, इसलिए आप नहीं चाहते कि उन्हें नया स्कूल डालने पर दोबारा डाला जाए।

प्रारंभ में आप इस तरह की संस्थाओं को परिभाषित कर सकते हैं:

public class City
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class School
{
    public int Id { get; set; }
    public string Name { get; set; }

    [Required]
    public City City { get; set; }
}

और आप इस तरह के स्कूल सम्मिलन कर सकते हैं (मान लीजिए कि आपके पास पहले से ही नई संपत्ति को सौंपा गया शहर संपत्ति है):

public School Insert(School newItem)
{
    using (var context = new DatabaseContext())
    {
        context.Set<School>().Add(newItem);
        // use the following statement so that City won't be inserted
        context.Entry(newItem.City).State = EntityState.Unchanged;
        context.SaveChanges();
        return newItem;
    }
}

उपरोक्त दृष्टिकोण इस मामले में पूरी तरह से काम कर सकता है, हालांकि, मैं विदेशी कुंजी दृष्टिकोण पसंद करता हूं जो मेरे लिए अधिक स्पष्ट और लचीला है। नीचे अद्यतन समाधान देखें:

public class City
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class School
{
    public int Id { get; set; }
    public string Name { get; set; }

    [ForeignKey("City_Id")]
    public City City { get; set; }

    [Required]
    public int City_Id { get; set; }
}

इस तरह, आप स्पष्ट रूप से परिभाषित करते हैं कि स्कूल की एक विदेशी कुंजी सिटी_आईडी है और यह शहर इकाई को संदर्भित करती है। तो जब स्कूल के सम्मिलन की बात आती है, तो आप कर सकते हैं:

    public School Insert(School newItem, int cityId)
    {
        if(cityId <= 0)
        {
            throw new Exception("City ID no provided");
        }

        newItem.City = null;
        newItem.City_Id = cityId;

        using (var context = new DatabaseContext())
        {
            context.Set<School>().Add(newItem);
            context.SaveChanges();
            return newItem;
        }
    }

इस मामले में, आप नए रिकॉर्ड के सिटी_आईडी को स्पष्ट रूप से निर्दिष्ट करते हैं और ग्राफ से शहर को हटाते हैं ताकि ईएफ स्कूल के साथ संदर्भ में इसे जोड़ने के लिए परेशान न हो।

हालांकि पहली छाप पर विदेशी कुंजी दृष्टिकोण अधिक जटिल लगता है, लेकिन मेरा विश्वास करो कि यह मानसिकता आपको बहुत से समय बचाएगी जब कई सारे रिश्तों को शामिल करने की बात आती है (इमेजिंग आपके पास स्कूल और छात्र संबंध है, और छात्र एक शहर संपत्ति है) और इतने पर।

यह आप के लिए उपयोगी है उम्मीद है।

Question

जब मैं इकाई ढांचे के साथ एक इकाई को सहेजता हूं, तो मैंने स्वाभाविक रूप से माना कि यह केवल निर्दिष्ट इकाई को सहेजने का प्रयास करेगा। हालांकि, यह उस इकाई की बाल संस्थाओं को बचाने की भी कोशिश कर रहा है। यह सभी प्रकार की अखंडता समस्याओं का कारण बन रहा है। मैं केवल उस इकाई को सहेजने के लिए ईएफ को कैसे मजबूर करूं जो मैं सहेजना चाहता हूं और इसलिए सभी बाल वस्तुओं को अनदेखा कर सकता हूं?

यदि मैं मैन्युअल रूप से गुणों को शून्य पर सेट करता हूं, तो मुझे एक त्रुटि मिलती है "ऑपरेशन विफल: रिश्ते को बदला नहीं जा सका क्योंकि एक या अधिक विदेशी-कुंजी गुण गैर-शून्य है।" यह बेहद काउंटर-उत्पादक है क्योंकि मैंने बाल वस्तु को विशेष रूप से शून्य पर सेट किया है ताकि ईएफ इसे अकेला छोड़ दे।

मैं बाल वस्तुओं को सहेजना / डालना क्यों नहीं चाहता हूं?

चूंकि टिप्पणियों में आगे और आगे चर्चा की जा रही है, इसलिए मैं कुछ औचित्य दूंगा कि मैं क्यों चाहता हूं कि मेरे बच्चे की वस्तुएं अकेले रहें।

मैं जिस अनुप्रयोग में निर्माण कर रहा हूं, उसमें ईएफ ऑब्जेक्ट मॉडल को डेटाबेस से लोड नहीं किया जा रहा है, लेकिन डेटा ऑब्जेक्ट्स के रूप में उपयोग किया जाता है जिसे मैं एक फ्लैट फ़ाइल को पार्स करते समय पॉपुलटिंग कर रहा हूं। बाल वस्तुओं के मामले में, इनमें से कई अभिभावक तालिका के विभिन्न गुणों को परिभाषित लुकअप टेबल का संदर्भ देते हैं। उदाहरण के लिए, प्राथमिक इकाई का भौगोलिक स्थान।

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

यहां तक ​​कि वास्तविक वस्तुओं वाले बच्चे की वस्तुओं के साथ, मुझे पहले माता-पिता को सहेजने और प्राथमिक कुंजी या ईएफ प्राप्त करने की आवश्यकता होती है, बस चीजों की गड़बड़ी होती है। उम्मीद है कि यह कुछ स्पष्टीकरण देता है।




सबसे पहले आपको यह जानना होगा कि ईएफ में इकाई को अपडेट करने के दो तरीके हैं।

  • संलग्न वस्तुओं

    जब आप ऊपर वर्णित विधियों में से किसी एक का उपयोग करके ऑब्जेक्ट संदर्भ से जुड़े ऑब्जेक्ट्स के संबंध को बदलते हैं, तो इकाई फ्रेमवर्क को सिंक में विदेशी कुंजी, संदर्भ और संग्रह रखने की आवश्यकता होती है।

  • डिस्कनेक्ट ऑब्जेक्ट्स

    यदि आप डिस्कनेक्ट किए गए ऑब्जेक्ट्स के साथ काम कर रहे हैं तो आपको सिंक्रनाइज़ेशन मैन्युअल रूप से प्रबंधित करना होगा।

मैं जिस अनुप्रयोग में निर्माण कर रहा हूं, उसमें ईएफ ऑब्जेक्ट मॉडल को डेटाबेस से लोड नहीं किया जा रहा है, लेकिन डेटा ऑब्जेक्ट्स के रूप में उपयोग किया जाता है जिसे मैं एक फ्लैट फ़ाइल को पार्स करते समय पॉपुलटिंग कर रहा हूं।

इसका मतलब है कि आप डिस्कनेक्ट ऑब्जेक्ट के साथ काम कर रहे हैं, लेकिन यह स्पष्ट नहीं है कि आप स्वतंत्र एसोसिएशन या विदेशी कुंजी एसोसिएशन का उपयोग कर रहे हैं या नहीं

  • जोड़ना

    मौजूदा बच्चे ऑब्जेक्ट (डेटाबेस में मौजूद ऑब्जेक्ट) के साथ नई इकाई जोड़ते समय, यदि बच्चे ऑब्जेक्ट को ईएफ द्वारा ट्रैक नहीं किया जाता है, तो बच्चे ऑब्जेक्ट को फिर से डाला जाएगा। जब तक आप पहले बच्चे ऑब्जेक्ट को मैन्युअल रूप से संलग्न नहीं करते हैं।

    db.Entity(entity.ChildObject).State = EntityState.Modified;
    db.Entity(entity).State = EntityState.Added;
    
  • अद्यतन करें

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

    db.Entity(entity).State = EntityState.Modified;
    

ग्राफ डिफ

यदि आप डिस्कनेक्ट ऑब्जेक्ट के साथ काम करते समय कोड को सरल बनाना चाहते हैं, तो आप ग्राफ diff लाइब्रेरी को ग्राफ़ करने का प्रयास कर सकते हैं।

यहां परिचय है, एंटीटी फ्रेमवर्क कोड के लिए ग्राफडिफ पेश करना - अलग-अलग इकाइयों के ग्राफ के स्वचालित अपडेट की अनुमति देना

नमूना कोड

  • अगर यह अस्तित्व में नहीं है, तो इकाई डालें, अन्यथा अद्यतन करें।

    db.UpdateGraph(entity);
    
  • अगर यह अस्तित्व में नहीं है तो इकाई डालें, अन्यथा अगर यह अस्तित्व में नहीं है तो बच्चे ऑब्जेक्ट को अपडेट और डालें, अन्यथा अपडेट करें।

    db.UpdateGraph(entity, map => map.OwnedEntity(x => x.ChildObject));
    



जब मैं प्रोफ़ाइल को सहेजने की कोशिश करता हूं तो मुझे वही समस्या मिलती है, मैं प्रोफाइल बनाने के लिए पहले से ही अभिवादन और नया टेबल करता हूं। जब मैं प्रोफ़ाइल डालता हूं तो यह अभिवादन में भी सम्मिलित होता है। इसलिए मैंने savechanges () से पहले ऐसा करने की कोशिश की।

डीबी.एन्ट्री (प्रोफाइल। सॉल्यूशन) .State = EntityState.Unchanged;




ऐसा करने का सबसे अच्छा तरीका आपके डेटाकॉन्टेक्स्ट में सेवचेंज फ़ंक्शन को ओवरराइड करना है।

    public override int SaveChanges()
    {
        var added = this.ChangeTracker.Entries().Where(e => e.State == System.Data.EntityState.Added);

        // Do your thing, like changing the state to detached
        return base.SaveChanges();
    }



हमने जो किया है वह माता-पिता को डीबीएसएटी में जोड़ने से पहले है, बच्चे के संग्रह को माता-पिता से डिस्कनेक्ट करें, मौजूदा संग्रहों को बाद में उनके साथ काम करने की अनुमति देने के लिए अन्य चरों पर धक्का देना सुनिश्चित करें, और फिर मौजूदा रिक्त संग्रह को नए खाली संग्रहों के साथ बदल दें। बच्चे के संग्रह को शून्य / कुछ भी नहीं सेट करना हमारे लिए असफल रहा। ऐसा करने के बाद माता-पिता को dbset में जोड़ें। इस तरह बच्चों को तब तक नहीं जोड़ा जाता जब तक आप उन्हें नहीं चाहते हैं।




Related