हमारी परियोजना में हम TransactionScope का उपयोग कर रहे हैं ताकि यह सुनिश्चित हो सके कि हमारे डेटा एक्सेस लेयर में यह लेनदेन है। हम अपने अंतिम-उपयोगकर्ता की मशीनों पर सक्षम होने के लिए MSDTC सेवा की आवश्यकता नहीं करने का लक्ष्य बना रहे हैं ।
परेशानी यह है कि हमारे डेवलपर्स मशीनों में से आधे पर, हम MSDTC के साथ अक्षम कर सकते हैं। दूसरे आधे हिस्से में यह सक्षम होना चाहिए या उन्हें "MSDTC पर [SERVER] उपलब्ध नहीं है" त्रुटि संदेश मिलता है।
यह वास्तव में मुझे अपना सिर खुजलाता है और मुझे गंभीरता से ADO.NET लेनदेन की वस्तुओं के आधार पर होम-स्पून TransactionScope- जैसे समाधान पर वापस जाने पर विचार कर रहा है। यह प्रतीत होता है पागल है - हमारे डेवलपर के आधे है पर एक ही कोड है कि काम करता है (और बढ़ा नहीं है) करता है अन्य डेवलपर पर बढ़ा।
मैं ट्रेस के बेहतर जवाब की उम्मीद कर रहा था कि डीटीसी को एक लेन-देन क्यों बढ़ाया गया है लेकिन दुर्भाग्य से ऐसा नहीं है।
यहां कोड का एक नमूना बिट है जो परेशानी का कारण होगा, मशीनों पर जो आगे बढ़ने की कोशिश करता है, यह दूसरे कनेक्शन पर बढ़ने की कोशिश करता है। ओपेन () (और हां, उस समय कोई अन्य कनेक्शन खुला नहीं है।)
using (TransactionScope transactionScope = new TransactionScope() {
using (SqlConnection connection = new SqlConnection(_ConStr)) {
using (SqlCommand command = connection.CreateCommand()) {
// prep the command
connection.Open();
using (SqlDataReader reader = command.ExecuteReader()) {
// use the reader
connection.Close();
}
}
}
// Do other stuff here that may or may not involve enlisting
// in the ambient transaction
using (SqlConnection connection = new SqlConnection(_ConStr)) {
using (SqlCommand command = connection.CreateCommand()) {
// prep the command
connection.Open(); // Throws "MSDTC on [SERVER] is unavailable" on some...
// gets here on only half of the developer machines.
}
connection.Close();
}
transactionScope.Complete();
}
हमने वास्तव में खोदा है और यह पता लगाने की कोशिश की है। यहाँ मशीनों पर कुछ जानकारी दी गई है जो इस पर काम करती है:
- देव 1: विंडोज 7 x64 SQL2008
- देव 2: विंडोज 7 x86 SQL2008
- देव 3: विंडोज 7 x64
SQL2005SQL2008
डेवलपर्स यह पर काम नहीं करता है:
- देव 4: विंडोज 7 x64,
SQL2008SQL2005 - देव 5: विंडोज विस्टा x86, SQL2005
- देव 6: विंडोज एक्सपी X86, SQL2005
- मेरा होम पीसी: विंडोज विस्टा होम प्रीमियम, x86, SQL2005
मुझे उस सभी मशीनों को जोड़ना चाहिए, जो समस्या का शिकार करने के प्रयास में, Microsoft अद्यतन से उपलब्ध सभी चीज़ों से पूरी तरह से समझौता कर चुकी हैं।
अपडेट 1:
- http://social.msdn.microsoft.com/forums/en-US/windowstransactionsprogramming/thread/a5462509-8d6d-4828-aefa-a197456081d3 एक समान समस्या का वर्णन करता है ... 2006 में वापस!
- http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope%28VS.80%29.aspx - उस कोड नमूने को पढ़ें, यह स्पष्ट रूप से एक नेस्टेड-दूसरा कनेक्शन (एक दूसरे SQL सर्वर के लिए) को प्रदर्शित करता है वास्तव में) जो डीटीसी को आगे बढ़ाएगा। हम अपने कोड में ऐसा नहीं कर रहे हैं - हम अलग-अलग SQL सर्वर का उपयोग नहीं कर रहे हैं, न ही विभिन्न कनेक्शन स्ट्रिंग्स का उपयोग कर रहे हैं, और न ही हमारे पास द्वितीयक कनेक्शन खोलने के लिए नेस्टेड हैं - डीटीसी में वृद्धि नहीं होनी चाहिए ।
- http://davidhayden.com/blog/dave/archive/2005/12/09/2615.aspx (2005 से) इस बारे में बात करता है कि SQL2000 से कनेक्ट होने पर DTC में वृद्धि हमेशा कैसे होगी। हम SQL2005 / 2008 का उपयोग कर रहे हैं
- लेनदेन में वृद्धि पर http://msdn.microsoft.com/en-us/library/ms229978.aspx MSDN।
MSDN ट्रांजेक्शन-एस्केलेशन पेज बताता है कि निम्नलिखित शर्तों के कारण DTC में लेनदेन बढ़ेगा:
- कम से कम एक टिकाऊ संसाधन जो एकल-चरण सूचनाओं का समर्थन नहीं करता है, लेन-देन में सूचीबद्ध है।
- कम से कम दो टिकाऊ संसाधन जो एकल-चरण सूचनाओं का समर्थन करते हैं, लेनदेन में सूचीबद्ध हैं। उदाहरण के लिए, किसी एकल कनेक्शन को सूचीबद्ध करने से लेन-देन को बढ़ावा नहीं मिलता है। हालाँकि, जब भी आप डेटाबेस से संबंधित डेटाबेस के लिए दूसरा कनेक्शन खोलते हैं, तो System.Transactions इंफ्रास्ट्रक्चर यह पता लगाता है कि यह लेन-देन का दूसरा टिकाऊ संसाधन है, और इसे MSDTC लेनदेन में आगे बढ़ाता है।
- एक अलग एप्लिकेशन डोमेन या अलग प्रक्रिया के लिए लेनदेन को "मार्शल" करने का अनुरोध किया जाता है। उदाहरण के लिए, एक एप्लिकेशन डोमेन सीमा के पार लेनदेन ऑब्जेक्ट का क्रमांकन। लेन-देन ऑब्जेक्ट को मार्शल्ड-बाय-वैल्यू है, जिसका अर्थ है कि इसे किसी एप्लिकेशन डोमेन सीमा (यहां तक कि उसी प्रक्रिया में) के माध्यम से पास करने का कोई भी प्रयास लेनदेन ऑब्जेक्ट के क्रमांकन में परिणाम करता है। आप ट्रांज़ेक्शन ऑब्जेक्ट को एक दूरस्थ विधि पर कॉल करके पास कर सकते हैं जो एक ट्रांज़ैक्शन को एक पैरामीटर के रूप में लेता है या आप एक दूरस्थ ट्रांसेक्शनल-सर्विस्ड घटक तक पहुँचने का प्रयास कर सकते हैं। यह लेन-देन ऑब्जेक्ट को क्रमबद्ध करता है और परिणाम में वृद्धि करता है, जब एक आवेदन डोमेन में लेनदेन को क्रमबद्ध किया जाता है। यह वितरित किया जा रहा है और स्थानीय लेनदेन प्रबंधक अब पर्याप्त नहीं है।
हम # 3 अनुभव नहीं कर रहे हैं। # 2 नहीं हो रहा है क्योंकि एक समय में केवल एक ही कनेक्शन होता है, और यह एक 'टिकाऊ संसाधन' के लिए भी होता है। क्या ऐसा कोई तरीका है जिससे # 1 हो सकता है? कुछ SQL2005 / 8 कॉन्फ़िगरेशन जो एकल-चरण सूचनाओं का समर्थन नहीं करने का कारण बनता है?
अपडेट 2:
पुन: जांच की गई, व्यक्तिगत रूप से, सभी के SQL सर्वर संस्करण - "Dev 3" में वास्तव में SQL2008 है, और "Dev 4" वास्तव में 5GB5 है। वह मुझे अपने सहकर्मियों पर फिर कभी भरोसा नहीं करना सिखाएगा। ;) डेटा में इस बदलाव के कारण, मुझे पूरा यकीन है कि हमें अपनी समस्या मिल गई है। हमारे SQL2008 डेवलपर्स समस्या का सामना नहीं कर रहे थे क्योंकि SQL2008 में भयानक मात्रा में प्रचुर मात्रा में शामिल है जो SQL2005 में नहीं है।
यह मुझे यह भी बताता है कि क्योंकि हम SQL2005 का समर्थन करने जा रहे हैं कि हम TransactionScope का उपयोग नहीं कर सकते हैं जैसे कि हम कर रहे हैं, और यदि हम TransactionScope का उपयोग करना चाहते हैं तो हमें एक एकल SqlConnection ऑब्जेक्ट को पास करने की आवश्यकता होगी ... जो स्थितियों में समस्याग्रस्त लगता है जहां SqlConnection को आसानी से पास नहीं किया जा सकता है ... यह सिर्फ ग्लोबल-SqlConnection उदाहरण की खुशबू आ रही है। प्यू!
अपडेट ३
बस यहाँ प्रश्न में स्पष्ट करने के लिए:
SQL2008:
- किसी एकल ट्रांज़ेक्शनस्कोप के भीतर कई कनेक्शनों को अनुमति देता है (जैसा कि उपरोक्त नमूना कोड में दिखाया गया है।)
- कैविएट # 1: यदि उन एकाधिक SqlConnections को नेस्टेड किया जाता है, अर्थात, दो या अधिक SqlConnections एक ही समय में खोले जाते हैं, तो TransactionScope तुरंत DTC में बढ़ जाएगा।
- कैविएट # 2: यदि एक अतिरिक्त SqlConnection एक अलग 'टिकाऊ संसाधन' के लिए खोला जाता है (यानी: एक अलग SQL सर्वर), तो यह तुरंत DTC तक बढ़ जाएगा
SQL2005:
- एक ही TransactionScope, अवधि के भीतर कई कनेक्शन की अनुमति नहीं देता है। जब दूसरा SqlConnection खोला जाएगा तो यह बढ़ जाएगा।
अद्यतन ४
और भी अधिक इस सवाल के मन में एक मेस की बस और अधिक स्पष्टता की खातिर के लिए उपयोगी है, और, आपके द्वारा एक साथ डीटीसी को आगे बढ़ाने के लिए SQL2005 प्राप्त कर सकते हैं एक SqlConnection
:
using (TransactionScope transactionScope = new TransactionScope()) {
using (SqlConnection connection = new SqlConnection(connectionString)) {
connection.Open();
connection.Close();
connection.Open(); // escalates to DTC
}
}
यह सिर्फ मेरे लिए टूटा हुआ लगता है, लेकिन मुझे लगता है कि मैं समझ सकता हूं कि क्या हर कॉल SqlConnection.Open()
कनेक्शन पूल से हथियाने के लिए है।
"ऐसा क्यों हो सकता है, हालांकि?" यदि आप इसे खोलने से पहले उस कनेक्शन के खिलाफ SqlTableAdapter का उपयोग करते हैं, तो, SqlTableAdapter कनेक्शन को खोल देगा और बंद कर देगा, प्रभावी रूप से आपके लिए लेन-देन को समाप्त कर देगा क्योंकि अब आप इसे फिर से नहीं खोल सकते।
इसलिए, मूल रूप से, SQL2005 के साथ TransactionScope का सफलतापूर्वक उपयोग करने के लिए आपको कुछ प्रकार के वैश्विक कनेक्शन ऑब्जेक्ट की आवश्यकता होती है जो कि पहले TransactionScope के बिंदु से खुला रहता है, जब तक कि अब इसकी आवश्यकता न हो। एक वैश्विक कनेक्शन ऑब्जेक्ट की कोड-गंध के अलावा, पहले कनेक्शन को खोलना और इसे अंतिम रूप से बंद करना जितना संभव हो उतना देर से कनेक्शन खोलने और जल्द से जल्द इसे बंद करने के तर्क के खिलाफ है।