एंटिटी फ्रेमवर्क 4 - AddObject बनाम अटैच


132

मैं हाल ही में एंटिटी फ्रेमवर्क 4 के साथ काम कर रहा हूं , और ObjectSet.Attach , और ObjectSet.AddObject का उपयोग करने के लिए थोड़ा उलझन में हूं

मेरी समझ से:

  • "अटैच" का उपयोग करें जब सिस्टम में एक इकाई पहले से मौजूद है
  • बिल्कुल नया इकाई बनाते समय "AddObject" का उपयोग करें

इसलिए, अगर मैं एक नया व्यक्ति बना रहा हूं, तो मैं ऐसा करता हूं ।

var ctx = new MyEntities();
var newPerson = new Person { Name = "Joe Bloggs" };
ctx.Persons.AddObject(newPerson);
ctx.SaveChanges();

यदि मैं किसी मौजूदा व्यक्ति को संशोधित कर रहा हूं , तो मैं यह करता हूं:

var ctx = new MyEntities();
var existingPerson = ctx.Persons.SingleOrDefault(p => p.Name = "Joe Bloggs" };
existingPerson.Name = "Joe Briggs";
ctx.SaveChanges();

ध्यान रखें, यह एक बहुत ही सरल उदाहरण है। वास्तव में मैं शुद्ध POCO (कोई कोड पीढ़ी), रिपॉजिटरी पैटर्न (ctx.Persons के साथ सौदा नहीं), और कार्य की इकाई (ctx.SaveChanges के साथ सौदा नहीं) का उपयोग कर रहा हूं। लेकिन "कवर के तहत", उपरोक्त वही है जो मेरे कार्यान्वयन में होता है।

अब, मेरा प्रश्न - मुझे अभी तक एक परिदृश्य नहीं मिला है जहाँ मुझे अटैच का उपयोग करना पड़ा हो ।

मुझे यहां क्या समझ नहीं आ रहा है? हमें अटैच का उपयोग कब करना है?

संपादित करें

बस स्पष्ट करने के लिए, मुझे AddObject (या इसके विपरीत) पर अटैच का उपयोग करने के उदाहरणों की तलाश है ।

EDIT 2

नीचे दिया गया उत्तर सही है (जिसे मैंने स्वीकार किया है), लेकिन मुझे लगा कि मैं एक और उदाहरण जोड़ूंगा जहां अटैच उपयोगी होगा।

मौजूदा व्यक्ति को संशोधित करने के लिए मेरे उपरोक्त उदाहरण में , दो प्रश्नों को वास्तव में निष्पादित किया जा रहा है।

एक व्यक्ति (.SingleOrDefault) को पुनः प्राप्त करने के लिए, और दूसरा UPDATE (.SaveChanges) करने के लिए।

यदि (किसी कारण से), मुझे पहले से ही पता था कि "जो ब्लॉग्स" सिस्टम में मौजूद है, तो उसे पाने के लिए एक अतिरिक्त क्वेरी क्यों करें? मैं ऐसा कर सकता था:

var ctx = new MyEntities();
var existingPerson = new Person { Name = "Joe Bloggs" };
ctx.Persons.Attach(existingPerson);
ctx.SaveChanges();

इसके परिणामस्वरूप केवल एक अद्यतन विवरण निष्पादित किया जाएगा।


अटैचमेंट का उपयोग MVC में अब उन दिनों में किया जाता है जब पुटिंग मॉडल सीधे EF में वापस आते हैं। बहुत अच्छी तरह से काम करता है और कोड लाइनों की एक टन बचाता है।
पायोटर कुला

जवाबों:


162

ObjectContext.AddObject और ObjectSet.AddObject : AddObject विधि नव निर्मित वस्तुओं है कि है जोड़ने के लिए है नहीं डेटाबेस में मौजूद हैं। इकाई को स्वचालित रूप से जेनरेट किया गया अस्थायी एंटिटीके मिल जाएगाऔर इसकी एंटिटीस्टैट को जोड़ा जाएगा । जब SaveChanges को कॉल किया जाता है, तो यह EF को स्पष्ट होगा कि इस इकाई को डेटाबेस में डाला जाना चाहिए।

ObjectContext.Attach और ObjectSet.Attach :
दूसरी ओर, अटैच का उपयोग उन संस्थाओं के लिए किया जाता है जो पहले से हीडेटाबेस में मौजूद हैं । EntityState को जोड़ा जाने के बजाय, एक अपरिवर्तित EntityStateमें संलग्न करें, जिसका अर्थ है कि यह संदर्भ में संलग्न होने के बाद से परिवर्तित नहीं हुआ है। जिन वस्तुओं को आप संलग्न कर रहे हैं, उन्हें डेटाबेस में मौजूद माना जाता है। यदि आप ऑब्जेक्ट्स संलग्न किए जाने के बाद उन्हें संशोधित करते हैं, तो जब आप SaveChanges को कॉल करते हैं तो EntityKey का मान db तालिका में उसकी मिलान आईडी ढूंढकर उपयुक्त पंक्ति को अपडेट (या डिलीट) करने के लिए उपयोग किया जाता है।

इसके अलावा, अटैच विधि का उपयोग करके, आप पहले से ही ObjectContext में मौजूद संस्थाओं के बीच संबंधों को परिभाषित कर सकते हैं लेकिन यह हैस्वचालित रूप से कनेक्ट नहीं किया गया है। मूल रूप से अटैच का मुख्य उद्देश्य, उन संस्थाओं को जोड़ना है जो पहले से ही ObjectContext से जुड़े हुए हैं औरनए नहीं हैं , इसलिए आप ऐसी संस्थाओं का उपयोग नहीं कर सकते हैं, जिनका EntityState जोड़ा गया है। आपकोइस स्थिति में Add () का उपयोग करना होगा।

उदाहरण के लिए, मान लें कि आपकी व्यक्तिगत इकाई के पास पते के नाम से एक नेविगेशन संपत्ति हैजो पता इकाईका एक संग्रह है। मान लीजिए कि आपने दोनों वस्तुओं को संदर्भ से पढ़ा है, लेकिन वे एक-दूसरे से संबंधित नहीं हैं और आप इसे बनाना चाहते हैं:

var existingPerson = ctx.Persons.SingleOrDefault(p => p.Name = "Joe Bloggs" };
var myAddress = ctx.Addresses.First(a => a.PersonID != existingPerson.PersonID);
existingPerson.Addresses.Attach(myAddress);
// OR:
myAddress.PersonReference.Attach(existingPerson)
ctx.SaveChanges();

उत्तर के लिए धन्यवाद, मैं दो (उर्फ पहले दो पैराग्राफ) की परिभाषा को समझता हूं। लेकिन मैं एक परिदृश्य को नहीं समझता जहाँ मुझे अटैच का उपयोग करने की आवश्यकता है। आपका अंतिम पैराग्राफ वास्तव में मेरे लिए मायने नहीं रखता है (मूल रूप से पहले दो पैराग्राफ के संयोजन की तरह पढ़ता है), क्या आप मुझे एक उदाहरण दे सकते हैं कि मैं अपने उपरोक्त परिदृश्य में "अटैच" का उपयोग कहां करूंगा? यह वास्तव में क्या im की तलाश है - उदाहरण, परिभाषाएं नहीं। वास्तव में अपने समय की सराहना करते हैं। :)
RPM1984

1
कोई समस्या नहीं है, मैंने पिछले पैराग्राफ को स्पष्ट करने के लिए एक कोड स्निपेट जोड़ा है, जैसा कि आप देख सकते हैं कि हमारे पास 2 असंबंधित वस्तुएं हैं और उन्हें एक दूसरे से संबंधित करने में हमारी सहायता करें। अन्य उदाहरण एक अटैच () विधि का उपयोग एक "अलग इकाई" को संदर्भ में संलग्न करने के लिए होगा (ऐसे कई कारण हैं जो आप चाहते हैं कि एक अलग इकाई को संदर्भ में वापस संलग्न किया जा सकता है)
मोर्टेज़ा मनवी

1
हाँ, मैं अभी मिल गया। मैंने अभी EF4 (जूली लर्मन द्वारा) पर एक TechEd vid देखा, जिसने एक उदाहरण दिखाया। आपके पास एक इकाई हो सकती है, जिसे आपने किसी क्वेरी से पुनर्प्राप्त नहीं किया है (अर्थात यह डाइकनेक्टेड है), लेकिन आप जानते हैं कि यह मौजूद है, इसलिए आप उस इकाई पर एक अद्यतन करने के लिए अटैच का उपयोग करते हैं। समझ में आता है, हालांकि मैं अभी भी एक परिदृश्य को बढ़ाने के लिए संघर्ष कर रहा हूं जहां आपके पास "डिस्कनेक्ट" इकाई होगी। आपकी सहायता के लिए धन्यवाद।
RPM1984

1
महान। क्या मैं आपसे अन्य साथी डेवलपर्स के लिए वीडियो का लिंक साझा करने के लिए कह सकता हूं जो इस पोस्ट को पढ़ने के लिए हो सकता है?
मोर्टेजा मनावी

3
ऊपर दी गई लिंक RPM1984 द्वारा साझा टूट गया है, यह अब पर भेज दिया जाएगा channel9.msdn.com/Events/TechEd/NorthAmerica/2010/DEV205 । का आनंद लें
स्टैक किया गया

31

यह एक देर से प्रतिक्रिया है, लेकिन यह दूसरों को यह खोजने में मदद कर सकता है।

मूल रूप से, "डिस्कनेक्ट" इकाई तब हो सकती है जब आप "उपयोग" गुंजाइश के बाहर किसी इकाई को हेरफेर करते हैं।

Employee e = null;

using (var ctx = new MyModelContainer())
{
     e = ctx.Employees.SingleOrDefault(emp => emp .....);
}

using (var ctx2 = new MyModelContainer())
{
     e; // This entity instance is disconnected from ctx2
}

यदि आप एक और "स्कोप" का उपयोग करते हुए प्रवेश करते हैं तो "ई" वेरिएबल डिस्कनेक्ट हो जाएगा क्योंकि यह पिछले "स्कोप" का उपयोग करता है और चूंकि पिछले "स्कोप" का उपयोग किया जाता है, तो "ई" डिस्कनेक्ट हो जाता है।

यही मैं इसे समझता हूं।


3
Tchi का उदाहरण एक उत्कृष्ट और सरल उदाहरण है - हाँ, कर्मचारी चर को बाहर घोषित किया जाना चाहिए। दायरे के बाहर e.Address.Street का प्रयास करें और एक अशक्त संदर्भ अपवाद पॉप-अप देखें। यदि आप संलग्न करते हैं, तो आवेदन को दूसरे दायरे में कर्मचारी के लिए डीबी में वापस नहीं जाना होगा।
स्टीव

9

यह प्रोग्रामिंग एंटिटी फ्रेमवर्क: DbContext का एक उद्धरण है

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

private static void TestDeleteDestination()
{
    Destination canyon;
    using (var context = new BreakAwayContext())
    {
        canyon = (from d in context.Destinations
        where d.Name == "Grand Canyon"
        select d).Single();
    }
    DeleteDestination(canyon);
}
private static void DeleteDestination(Destination destination)
{
    using (var context = new BreakAwayContext())
    {
        context.Destinations.Attach(destination);
        context.Destinations.Remove(destination);
        context.SaveChanges();
    }
}

TestDeleteDestination विधि सर्वर से मौजूदा डेस्टिनेशन को प्राप्त करने वाले एक क्लाइंट एप्लिकेशन का अनुकरण करती है और फिर इसे सर्वर पर DeleteDestination विधि से पास करती है। DeleteDestination विधि संदर्भ को यह बताने के लिए अटैच विधि का उपयोग करती है कि यह एक मौजूदा गंतव्य है। तब हटाए जाने के लिए मौजूदा गंतव्य को पंजीकृत करने के लिए निकालें विधि का उपयोग किया जाता है


-8

अटैचमेंट के बजाय केवल प्राथमिक कुंजी को संदर्भित करने के बारे में क्या?

अर्थात:

var existingPerson = ctx.Persons.SingleOrDefault(p => p.Name = "Joe Bloggs" };
var myAddress = ctx.Addresses.First(a => a.PersonID != existingPerson.PersonID);
existingPerson.AddressId = myAddress.Id // not -> existingPerson.Addresses.Attach(myAddress);
// OR:
myAddress.Person.Id = existingPerson.Id // not -> myAddress.PersonReference.Attach(existingPerson);
ctx.SaveChanges();
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.