2008-11-06 13 views
16

के भीतर भी बंद नहीं किया जा रहा है कृपया मदद करें!.net SqlConnection किसी भी {{

पृष्ठभूमि की जानकारी

मैं एक WPF आवेदन जो एक SQL सर्वर 2005 डेटाबेस तक पहुँचता है। डेटाबेस उस मशीन पर स्थानीय रूप से चल रहा है जिस पर एप्लिकेशन चल रहा है।

हर जगह मैं लिंक डेटाकॉन्टेक्स्ट का उपयोग करता हूं, मैं एक {{} कथन का उपयोग करता हूं, और एक फ़ंक्शन के परिणामस्वरूप पास करता हूं जो एक SQLLonnection ऑब्जेक्ट देता है जिसे खोला गया है और डेटाकॉन्टेक्स्ट कन्स्ट्रक्टर पर लौटने से पहले इसका उपयोग कर SQLLommand निष्पादित किया गया था .. अर्थात

// In the application code 
using (DataContext db = new DataContext(GetConnection())) 
{ 
    ... Code 
} 

जहां getConnection इस तरह दिखता है (मैं समारोह से 'फुलाना' यह अधिक पठनीय बनाने के लिए बाहर छीन लिया गया है, लेकिन वहाँ कोई अतिरिक्त कार्यक्षमता है कि याद आ रही है है)।

// Function which gets an opened connection which is given back to the DataContext constructor 
public static System.Data.SqlClient.SqlConnection GetConnection() 
{ 
    System.Data.SqlClient.SqlConnection Conn = new System.Data.SqlClient.SqlConnection(/* The connection string */); 

    if (Conn != null) 
    { 
     try 
     { 
      Conn.Open(); 
     } 
     catch (System.Data.SqlClient.SqlException SDSCSEx) 
     { 
      /* Error Handling */ 
     } 

     using (System.Data.SqlClient.SqlCommand SetCmd = new System.Data.SqlClient.SqlCommand()) 
     { 
      SetCmd.Connection = Conn; 
      SetCmd.CommandType = System.Data.CommandType.Text; 

      string CurrentUserID = System.String.Empty; 
      SetCmd.CommandText = "DECLARE @B VARBINARY(36); SET @B = CAST('" + CurrentUserID + "' AS VARBINARY(36)); SET CONTEXT_INFO @B"; 

      try 
      { 
       SetCmd.ExecuteNonQuery(); 
      } 
      catch (System.Exception) 
      { 
       /* Error Handling */ 
      } 
     } 

     return Conn; 
    } 

मुझे नहीं लगता कि आवेदन एक WPF एक होने के मुद्दे को मैं कर रहा हूँ पर कोई प्रभाव पड़ता है है।

मुद्दा मैं

SqlConnection के बावजूद हो रहा है Sql सर्वर प्रबंधन स्टूडियो मैं अभी भी साथ खुले कनेक्शनों का भार देख सकते में DataContext के साथ निपटाया जा रहा है:

status : 'Sleeping' 
command : 'AWAITING COMMAND' 
last SQL Transact Command Batch : DECLARE @B VARBINARY(36); SET @B = CAST('GUID' AS VARBINARY(36)); SET CONTEXT_INFO @B 

अंततः कनेक्शन पूल का उपयोग किया जाता है और आवेदन जारी नहीं रह सकता है।

तो मैं केवल यह निष्कर्ष निकाल सकता हूं कि किसी भी तरह Context_Info सेट करने के लिए SQLCommand को चलाने का अर्थ यह है कि डेटा कॉन्टेक्स्ट का निपटारा होने पर कनेक्शन का निपटारा नहीं किया जाता है।

क्या कोई भी इस बात को स्पष्ट कर सकता है कि कनेक्शन को बंद होने से रोक दिया जाएगा और जब डेटाकॉन्टेक्स्ट का उपयोग किया जाता है तो इसका निपटारा किया जाता है?

उत्तर

19

MSDN (DataContext Constructor (IDbConnection)) से:

आप खुले कनेक्शन प्रदान करते हैं, DataContext यह बंद नहीं होगा। इसलिए, डेटा कॉन्टेक्स्ट को एक खुले कनेक्शन के साथ तत्काल न करें जब तक आपके पास ऐसा करने का कोई अच्छा कारण न हो।

तो मूल रूप से, ऐसा लगता है कि आपके कनेक्शन जीसी के रिलीज होने से पहले उन्हें अंतिम रूप देने के लिए इंतजार कर रहे हैं। यदि आपके पास बहुत सारे कोड हैं जो ऐसा करते हैं, तो डेटा-संदर्भ के आंशिक वर्ग में Dispose() से अधिक हो सकता है, और कनेक्शन बंद कर सकता है - बस यह सुनिश्चित करना सुनिश्चित करें कि डेटा-संदर्भ कनेक्शन के स्वामित्व को मानता है!

protected override void Dispose(bool disposing) 
    { 
     if(disposing && this.Connection != null && this.Connection.State == ConnectionState.Open) 
     { 
      this.Connection.Close(); 
      this.Connection.Dispose(); 
     } 
     base.Dispose(disposing); 
    } 

व्यक्तिगत रूप से, मैं खुशी से यह देना होगा (नियमित डेटा संदर्भ, w/ओ ऊपर हैक) एक खुला कनेक्शन के रूप में जब तक मैं कनेक्शन "का उपयोग कर" किया गया था (कई कार्य करने के लिए मुझे अनुमति देता है) - अर्थात

using(var conn = GetConnection()) 
{ 
    // snip: some stuff involving conn 

    using(var ctx = new FooContext(conn)) 
    { 
     // snip: some stuff involving ctx 
    } 

    // snip: some more stuff involving conn 
} 
0

Dispose कनेक्शन बंद हो जाना चाहिए, के रूप में MSDN बताते हैं:

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

मेरा अनुमान है कि आपकी समस्या GetContext() के साथ कुछ करने के लिए है।

7

LINQ DataContext द्वारा उपयोग किए गए SqlProvider केवल SQL कनेक्शन को बंद कर देता है (SqlConnectionManager.DisposeConnection के माध्यम से) यदि यह इसे खोलने वाला था। यदि आप पहले से ही SqlConnection ऑब्जेक्ट DataContext कन्स्ट्रक्टर को देते हैं, तो यह आपके लिए बंद नहीं होगा। इस प्रकार, आप लिखना चाहिए:

using (SqlConnection conn = GetConnection()) 
using (DataContext db = new DataContext(conn)) 
{ 
    ... Code 
} 
1

मैं कनेक्शन लगता है, जबकि अब कोई संदर्भित, जीसी पूरी तरह से नष्ट करने के लिए इंतज़ार कर रहा है।

समाधान:

अपनी खुद की DataContext वर्ग जो स्वत: जनरेट एक से निकला है बनाएँ। (आधार का नाम बदलें ताकि आपको कोई अन्य कोड बदलना पड़े)।

आपके व्युत्पन्न डेटाकॉन्टेक्स्ट में - एक निपटान() फ़ंक्शन जोड़ें। उसमें - आंतरिक कनेक्शन का निपटान करें।

+0

आप स्वत: जेनरेट किए गए डेटा-संदर्भ को विस्तारित करने के लिए केवल आंशिक कक्षा जोड़ सकते हैं; subclass करने की कोई ज़रूरत नहीं है। –

1

मदद लोग के लिए अच्छी तरह से धन्यवाद, यह अब हल किया गया है ..

अनिवार्य रूप से मैं ऊपर अधिकतर उत्तर के तत्वों लिया और जैसा कि ऊपर DataContext निर्माता लागू किया (मैं पहले से ही कंस्ट्रक्टर्स अतिभारित था तो यह 'नहीं था एक बड़ा परिवर्तन नहीं)।

// Variable for storing the connection passed to the constructor 
private System.Data.SqlClient.SqlConnection _Connection; 

public DataContext(System.Data.SqlClient.SqlConnection Connection) : base(Connection) 
{ 
    // Only set the reference if the connection is Valid and Open during construction 
    if (Connection != null) 
    { 
     if (Connection.State == System.Data.ConnectionState.Open) 
     { 
      _Connection = Connection;      
     } 
    }   
} 

protected override void Dispose(bool disposing) 
{   
    // Only try closing the connection if it was opened during construction  
    if (_Connection!= null) 
    { 
     _Connection.Close(); 
     _Connection.Dispose(); 
    } 

    base.Dispose(disposing); 
} 

उपरोक्त सुझावों में से कुछ के बजाय ऐसा करने के लिए कारण यह है कि निपटाने विधि में this.Connection तक पहुँचने फेंकता एक ObjectDisposedException है।

और उपरोक्त कार्यों के साथ-साथ मैं उम्मीद कर रहा था!

+0

अरे, मैंने यही कहा। मुझे स्मार्ट होना चाहिए। – GeekyMonkey

3

मुझे एंटिटी फ्रेमवर्क का उपयोग करके एक ही समस्या का अनुभव हुआ। मेरा ObjectContextusing ब्लॉक के चारों ओर लपेटा गया था।

एक कनेक्शन स्थापित किया गया था जब मैं SaveChanges() कहा जाता है, लेकिन उसके बाद using बयान दायरे से बाहर था, मैंने देखा है कि एसक्यूएल प्रबंधन स्टूडियो अभी भी नेट एसक्यूएल ग्राहक के लिए एक "AWAITING COMMAND" था। ऐसा लगता है कि इसे ADO.NET प्रदाता के व्यवहार से करना है जिसमें डिफ़ॉल्ट रूप से कनेक्शन पूलिंग चालू है।

कनेक्शन पूलिंग बार है कि नए कनेक्शन खोला जाना आवश्यक की संख्या कम कर देता है:

MSDN (जोर मेरा) पर "कनेक्शन एसक्यूएल सर्वर साथ पूलिंग का उपयोग " से

। पूलर भौतिक कनेक्शन के स्वामित्व को बनाए रखता है। यह प्रत्येक दिए गए कनेक्शन कॉन्फ़िगरेशन के लिए सक्रिय कनेक्शन का एक सेट जीवित रखकर कनेक्शन प्रबंधित करता है। जब भी कोई उपयोगकर्ता कनेक्शन पर Open पर कॉल करता है, तो पूलर यह देखने के लिए देखता है कि पूल में कोई उपलब्ध कनेक्शन है या नहीं। यदि एक पूल कनेक्शन उपलब्ध है, तो यह एक नया कनेक्शन खोलने के बजाय कॉलर को वापस कर देता है। जब एप्लिकेशन कनेक्शन पर Close पर कॉल करता है, तो पूलर इसे वास्तव में बंद करने के बजाय सक्रिय कनेक्शन के पूल सेट पर लौटाता है। एक बार कनेक्शन पूल में वापस आ जाने के बाद, यह अगले Open कॉल पर पुन: उपयोग करने के लिए तैयार है।

इसके अलावा ClearAllPools और ClearPool यदि आवश्यक हो तो स्पष्ट रूप से सभी जमा कनेक्शन बंद करने के लिए उपयोगी है।

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