2010-02-18 10 views
8

.NET में एंटीटी फ्रेमवर्क का उपयोग करना मैं डेटाबेस से लौटाई गई वस्तुओं की सूची के माध्यम से लूप करना चाहता हूं और अपडेट कर सकता हूं। http://social.msdn.microsoft.com/Forums/en/adodotnetentityframework/thread/8a337036-d288-48d4-80d4-89e5a51eddd9?ppud=4 एस Hargroves एक IList में परिवर्तित करने का सुझाव और कहा कि समाधान है:.NET EntityFramework: "प्रदाता कनेक्शन पर लेनदेन शुरू करते समय एक त्रुटि आई। विवरण के लिए आंतरिक अपवाद देखें"

var qry = (from c in DBEntities.Customer select c); 
foreach (Object item in qry) 
{ 
    item.FirstName = .... 
    ... etc, other code here 
    DBEntities.SaveChanges(); 
} 
के अनुसार

कोशिश नहीं की है, मुझे यकीन है कि यह काम करेगा, लेकिन यह भी काम करता है, मैं जानना चाहता हूं कि मैं लूप के दौरान आइटम को अपडेट क्यों नहीं कर सकता? यह मेरे स्थानीय विकास पर्यावरण पर होता है, जिसमें कोई अन्य उपयोगकर्ता डेटाबेस को मारता नहीं है।

धन्यवाद ...

+0

क्या भीतरी अपवाद कहा? आम तौर पर, आपको अपवादों को पकड़ना चाहिए, फिर 'ex.ToString() 'के परिणाम पोस्ट करना चाहिए। आपको तब "फेंक देना चाहिए" दोबारा, चूंकि "ex.ToString()" अपवाद को संभाल नहीं करता है। –

उत्तर

3

मैं var सूची बनाने के साथ सहमत हूं। फिर अपने foreach में, qry में ऑब्जेक्ट आइटम का उपयोग करने के बजाय, qry में ग्राहक ग्राहक का उपयोग करें। उस परिदृश्य में आप वास्तव में ऑब्जेक्ट्स न केवल ऑब्जेक्ट्स के साथ काम कर रहे हैं। ज्यादातर मामलों में आप SaveChanges() को फ़ोरैच में कॉल नहीं करना चाहते हैं क्योंकि यह निष्पादित होने पर सर्वर पर एक अद्यतन कमांड निष्पादित करने जा रहा है। यदि आप इसे foreach के बाद करते हैं तो यह डेटाबेस में कॉल का एक बैच बना देगा और बहुत अच्छा प्रदर्शन करेगा।

मेरे द्वारा सुझाए गए छद्म कोड की तरह

var customers = (from c in DBEntities.Customer select c).ToList<Customer>(); 
foreach (Customer customer item in customers) 
{ 
    customer.FirstName = .... 
    ... etc, other code here 

} 
DBEntities.SaveChanges(); 
0

पाश के बाद SavingChanges पर सिफारिश के लिए धन्यवाद कुछ, मुझे लगता है कि नहीं सोचा था लग रहा है। हालांकि मुझे 1 मिलियन से अधिक रिकॉर्ड संसाधित करना है, यह इतना अधिक नहीं है, लेकिन कुछ प्रसंस्करण है जो प्रत्येक पाश के दौरान किया जाएगा। तो मैं थोड़ा चिंतित हूं कि जानकारी अपडेट करने में 1 मिलियन रिकॉर्ड लूप करने में काफी समय लगेगा और फिर बदलावों को पोस्ट करने में कुछ समय लगेगा।

मुझे यह भी पता है कि EntityFramework शायद सबसे अच्छा तरीका नहीं है, लेकिन मुझे एंटीटी फ्रेमवर्क की विशेषताओं और सीमाओं को सीखने में रूचि है।

यह भी ध्यान दें कि var सूची वास्तव में ग्राहक प्रकार का ऑब्जेक्टक्वायर देता है। तो फोरैच लूप वास्तव में ऊपर सूचीबद्ध के रूप में ग्राहक चर डेटा प्रकार का उपयोग कर सूची में परिवर्तित किए बिना भी लिखा जा सकता है।

फिर से मेरा प्रश्न है कि मैं जानना चाहता हूं कि मैं लूप के दौरान एक ही संदर्भ ऑब्जेक्ट (डीबीईएनटीटीएस) में कोई परिवर्तन क्यों नहीं पोस्ट कर सकता हूं?

+2

आप अपने प्रश्न के उत्तर के रूप में अधिक जानकारी पोस्ट नहीं करते हैं, इसके बजाय आप मूल प्रश्न संपादित करते हैं। – StarCub

11

जब आप एक क्वेरी पर SaveChanges का उपयोग कर डेटाबेस को अद्यतन करते हैं, तो क्वेरी को अमान्य कर दिया जाता है। आपके द्वारा किए गए अपडेट द्वारा परिणाम सेट बदल दिया गया हो सकता है।

ToList का उपयोग करके, आप क्वेरी के निष्पादन को ट्रिगर कर रहे हैं और डेटाबेस से सभी परिणामों को स्मृति में ला रहे हैं। आपकी इन-मेमोरी सूची अब ठोस है और अब एक प्रश्न होने से संबंधित नहीं है।

क्योंकि ऑब्जेक्ट क्वेरीज़ IEnumerable का उपयोग करती हैं, तो ऐसा कुछ ठीक नहीं है जो किसी फ़ोरैच में सूची को संशोधित करता है।

मैं भी मानते हैं कि यह कोड एक ही मूल कारणों से विफल होगा:

List<int> numbers = new List<int>() { 1,2,3,4,5,6}; 
foreach(var num in numbers) 
    numbers.Remove(num); //Invalidates the Enumerator being used in the foreach 
+0

कॉलिंग 'ToList' एक समाधान हो सकता है लेकिन क्या होगा यदि आपकी क्वेरी में 50,000 रिकॉर्ड या अधिक शामिल हैं? यह एक बार में स्मृति में खींचने के लिए हो सकता है और अंततः बहुत अधिक डेटा हो सकता है। –

+0

मूल कोड एक ही समस्या होगी। जहां तक ​​मुझे पता है, EF किसी ऑब्जेक्टक्चर की गणना करते समय परिणामों का कोई भी 'पेजिंग' नहीं करता है। आप मूल क्वेरी को बैचों में विभाजित करने का एक तरीका ढूंढ सकते हैं, या दो संदर्भ विकल्प का उपयोग कर सकते हैं जैसे @Ron – Tilendor

3

ठीक है, मैं एक ही मुद्दा में भाग लिया है। अभी मेरे पास केवल 20 के बारे में दस लाख रिकॉर्ड नहीं हैं, लेकिन तालिका मैं स्टोर छवियों को संसाधित करना चाहता हूं ताकि सूची में तालिका को प्रोसेस करते समय बहुत लंबा रास्ता लगे, यहां तक ​​कि डेस्कटॉप ऐप पर भी।

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

entityList _imgList = new entityList(); 
entityList _imgSave = new entityList(); 

// Now the 1st time I did this I got the whole record like follows. 

    var _imgList = _imgList.Images.where(i=> i.NotProcessed == false); 
    foreach(Images _img_p in imgList) 
    { 
     if(something) 
     { 
      Images _img = _imgSave.Single(i=> i.ID == _img_p.ID); 
      _img.NotProcessed == true; 
      imgSave.SaveChanges(); 
     } 
    } 
imgList.dispose(); 
imgSave.dispose(); 


// After i verified this worked I figured why do I need to whole record to loop though so I changed it to just get the ID then process my loop as follows, and it works great. 

    var _imgIds = _imgList.Images.where(i=> i.NotProcessed == false).select(i=>i.ID); 
    foreach(long _imgID in imgList) 
    { 
     Images _img = _imgSave.Single(i=> i.ID == _imgID); 
     if(something) 
     { 
      _img.NotProcessed == true; 
      imgSave.SaveChanges(); 
     } 
    } 

imgList.dispose(); 
imgSave.dispose(); 

तुम मेरे ब्लॉग पोस्ट में अधिक देख सकते हैं (ASP.Net Help Blog)

+0

पीएस सुझाता है। लूप काम करने के बाद परिवर्तनों को सहेजता है, लेकिन जब आपको देखने के समय लाइव होने के लिए परिवर्तन की आवश्यकता होती है तो यह नहीं होता है – Ron

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

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