एक वैश्विक इकाई फ्रेमवर्क बनाना DbContext एक वेब एप्लिकेशन में बहुत खराब है। डीबीकॉन्टेक्स्ट क्लास थ्रेड-सुरक्षित नहीं है (और एंटिटी फ्रेमवर्क v1 के ऑब्जेक्ट कॉन्टेक्स्ट के लिए समान है कक्षा)। इसे यूनिट ऑफ़ वर्क
की अवधारणा के आसपास बनाया गया है। और इसका मतलब है कि आप इसका उपयोग एकल उपयोग के मामले को संचालित करने के लिए करते हैं:इस प्रकार एक व्यावसायिक लेनदेन के लिए। यह एक ही अनुरोध को संभालने के लिए है।
आपको अपवाद इसलिए मिलता है क्योंकि प्रत्येक अनुरोध के लिए आप एक नया लेन-देन बनाते हैं, लेकिन उसी DbContext का उपयोग करने का प्रयास करें . आप भाग्यशाली हैं कि DbContext इसका पता लगाता है और एक अपवाद फेंकता है, क्योंकि अब आपको पता चला है कि यह काम नहीं करेगा।
डीबीकॉन्टेक्स्ट आपके डेटाबेस में संस्थाओं का एक स्थानीय कैश है। यह आपको परिवर्तनों का एक समूह बनाने और अंत में उन परिवर्तनों को डेटाबेस में जमा करने की अनुमति देता है। एकल स्थिर DbContext का उपयोग करते समय , कई उपयोगकर्ताओं के साथ SaveChanges . कॉल कर रहे हैं उस वस्तु पर, यह कैसे पता होना चाहिए कि वास्तव में क्या करना चाहिए और क्या नहीं करना चाहिए?
क्योंकि यह नहीं जानता, यह सब को सहेज लेगा परिवर्तन, लेकिन उस समय एक और अनुरोध अभी भी परिवर्तन कर रहा होगा। जब आप भाग्यशाली होते हैं, तो या तो EF या आपका डेटाबेस विफल हो जाएगा, क्योंकि निकाय अमान्य स्थिति में हैं। यदि आप बदकिस्मत हैं, तो अमान्य स्थिति में मौजूद संस्थाओं को सफलतापूर्वक डेटाबेस में सहेजा जाता है और आपको हफ्तों बाद पता चल सकता है कि आपका डेटा दूषित हो गया है।
आपकी समस्या का समाधान कम से कम एक डीबीकॉन्टेक्स्ट प्रति अनुरोध
. सिद्धांत रूप में आप उपयोगकर्ता सत्र में ऑब्जेक्ट संदर्भ को कैश कर सकते हैं, यह भी एक बुरा विचार है, क्योंकि उस स्थिति में DbContext आम तौर पर बहुत लंबे समय तक जीवित रहेगा और इसमें पुराना डेटा होगा (क्योंकि इसका आंतरिक कैश स्वचालित रूप से ताज़ा नहीं होगा)।
यह भी ध्यान रखें कि एक DbContext प्रति थ्रेड लगभग उतना ही बुरा है जितना कि संपूर्ण वेब एप्लिकेशन के लिए एक ही उदाहरण होना। ASP.NET एक थ्रेड पूल का उपयोग करता है जिसका अर्थ है कि वेब एप्लिकेशन के जीवनकाल के दौरान सीमित मात्रा में थ्रेड बनाए जाएंगे। इसका मूल रूप से मतलब है कि वे DbContext उस स्थिति में इंस्टेंस अभी भी एप्लिकेशन के जीवनकाल के लिए जीवित रहेंगे, जिससे डेटा की गति के साथ समान समस्याएं हो सकती हैं।
आप सोच सकते हैं कि एक DbContext प्रति थ्रेड वास्तव में थ्रेड-सुरक्षित है, लेकिन आमतौर पर ऐसा नहीं होता है, क्योंकि ASP.NET में एक एसिंक्रोनस मॉडल होता है जो इसे शुरू करने की तुलना में एक अलग थ्रेड पर अनुरोधों को पूरा करने की अनुमति देता है (और एमवीसी और वेब एपीआई के नवीनतम संस्करण भी एक की अनुमति देते हैं धागे की मनमानी संख्या अनुक्रमिक क्रम में एक एकल अनुरोध को संभालती है)। इसका मतलब यह है कि वह धागा जिसने अनुरोध शुरू किया और ObjectContext बनाया प्रारंभिक अनुरोध समाप्त होने से बहुत पहले किसी अन्य अनुरोध को संसाधित करने के लिए उपलब्ध हो सकता है। हालांकि उस अनुरोध में उपयोग की जाने वाली वस्तुएं (जैसे वेब पेज, नियंत्रक, या कोई व्यवसाय वर्ग), अभी भी उस DbContext को संदर्भित कर सकती हैं . चूंकि नया वेब अनुरोध उसी थ्रेड में चलता है, इसलिए उसे वही मिलेगा DbContext उदाहरण के रूप में पुराना अनुरोध क्या उपयोग कर रहा है। यह फिर से आपके आवेदन में दौड़ की स्थिति का कारण बनता है और वही थ्रेड-सुरक्षा मुद्दों का कारण बनता है जो एक वैश्विक DbContext उदाहरण के कारण।