2011-12-14 38 views
9

मैं कैसे एसक्यूएल सर्वर को साफ करते समय सीमा समाप्त हो SqlDependency वस्तुओं से छुटकारा पाने के लिए? SqlDepedency ऑब्जेक्ट से ईवेंट प्राप्त करने के बाद, मुझे एक नया ईवेंट प्राप्त करने से पहले मुझे एक नया निर्माण करने की आवश्यकता है। हालांकि, SQL सर्वर प्रक्रिया का स्मृति उपयोग तब तक चढ़ता है जब तक यह अनुमत स्मृति (SQL सर्वर एक्सप्रेस) से बाहर नहीं हो जाता। मैं पुराने प्रश्नों से कैसे छुटकारा पा सकता हूं?मैं SQL सर्वर मेमोरी से SqlDependency को कैसे साफ़ करूं?

कोड:

// Func: RegisterTableListener 
using (SqlConnection cn = new SqlConnection(Properties.Settings.Default.DatabseEventConnectionString)) 
{ 
if (cmd == null) 
{ 
    cmd = cn.CreateCommand(); 

    cmd.CommandType = CommandType.Text; 
    cmd.CommandText = "SELECT HostName, LastStatus, LastDetails, xml FROM dbo.[SystemTable]"; 
} 

lock (cmd) 
{ 
    cmd.Connection = cn; 
    cn.Open(); 
    cmd.Notification = null; 

    // creates a new dependency for the SqlCommand 
    if (dep == null) 
     dep = new SqlDependency(cmd); 
    // creates an event handler for the notification of data 
    //  changes in the database. 
    dep.OnChange += new OnChangeEventHandler(dependency_OnChange); 


    using (SqlDataReader reader = cmd.ExecuteReader()) 
    { 
    // code here to read 
    } 
} 
} 

// Func dependency_OnChange 
//SqlDependency dep = sender as SqlDependency; 
dep.OnChange -= dependency_OnChange; 
RegisterTableListener(); 
+0

आप 'SqlDependency' वस्तुओं कैसे बना रहे हैं? कृपया अपना कोड पोस्ट करें। क्या आप उनका सही तरीके से निपटान कर रहे हैं? – Oded

+0

बीमार कल जब मैं काम करता हूं तो कोड के साथ मेरी टिप्पणी अपडेट करें। Sudo: SqlDependency डीईपी = नए SqlDependency (cmd); डीपी।OnChange + = मज़ा; एसक्लड पर निर्भरता IDISposable – JeremyK

+0

लागू नहीं करता है मैंने कोड के साथ अद्यतन किया है। यहां तक ​​कि जब मैं एक SQLDddency का केवल एक उदाहरण चलाता हूं और हर बार रोकता हूं और प्रारंभ करता हूं, तो स्मृति चढ़ता है। मैं क्या हो रहा है के बारे में अनजान हूँ। – JeremyK

उत्तर

12

माइक्रोसॉफ्ट SqlDependency वर्ग के एक विशिष्ट व्यवहार नहीं है। भले ही आप SqlDependency.Stop() विधि, रिहाई SqlCommand और SqlConnection कहते हैं - यह अभी भी डेटाबेस में बातचीत समूहों (sys.conversation_groups) और बातचीत अंतिम बिंदुओं (sys.conversation_endpoints) रहता है। ऐसा लगता है कि SQL सर्वर प्रत्येक वार्तालाप समापन बिंदु लोड करता है और सभी अनुमत स्मृति का उपयोग करता है। Here परीक्षण जो इसे साबित करते हैं। तो, सभी अप्रयुक्त बातचीत अंतिम बिंदुओं को साफ और सभी पर कब्जा कर लिया स्मृति आप अपने डेटाबेस के लिए इस एसक्यूएल कोड शुरू कर दिया है जारी करने के लिए:

DECLARE @ConvHandle uniqueidentifier 
DECLARE Conv CURSOR FOR 
SELECT CEP.conversation_handle FROM sys.conversation_endpoints CEP 
WHERE CEP.state = 'DI' or CEP.state = 'CD' 
OPEN Conv; 
FETCH NEXT FROM Conv INTO @ConvHandle; 
WHILE (@@FETCH_STATUS = 0) BEGIN 
    END CONVERSATION @ConvHandle WITH CLEANUP; 
    FETCH NEXT FROM Conv INTO @ConvHandle; 
END 
CLOSE Conv; 
DEALLOCATE Conv; 

इसके अलावा, SqlDependency आप तालिका के सभी परिवर्तन प्राप्त करने का अवसर देना नहीं है। इसलिए, आपको SqlDependency पुनर्वसन के दौरान परिवर्तनों के बारे में अधिसूचना प्राप्त नहीं होती है।

इन सभी समस्याओं मैं SqlDependency वर्ग का एक और खुला स्रोत प्राप्ति का इस्तेमाल किया था से बचने के लिए - SqlDependencyEx। यह तालिका के परिवर्तनों के बारे में घटनाओं को प्राप्त करने के लिए डेटाबेस ट्रिगर और मूल सेवा ब्रोकर अधिसूचना का उपयोग करता है।

int changesReceived = 0; 
using (SqlDependencyEx sqlDependency = new SqlDependencyEx(
      TEST_CONNECTION_STRING, TEST_DATABASE_NAME, TEST_TABLE_NAME)) 
{ 
    sqlDependency.TableChanged += (o, e) => changesReceived++; 
    sqlDependency.Start(); 

    // Make table changes. 
    MakeTableInsertDeleteChanges(changesCount); 

    // Wait a little bit to receive all changes. 
    Thread.Sleep(1000); 
} 

Assert.AreEqual(changesCount, changesReceived); 

आशा इस मदद करता है: यह एक प्रयोग उदाहरण है।

+1

सीईपी.स्टेट = 'डी' या सीईपी.स्टेट = 'सीडी' कहां इस लाइन का अर्थ क्या है। आप क्या करने की कोशिश कर रहे हैं। कृपया मुझे समझने में मदद करें। धन्यवाद – Mou

+0

@Mou 'DI' का अर्थ है" डिस्कनेक्ट इनबाउंड ", 'सीडी' का अर्थ है" बंद "। इस अंक के साथ वार्तालापों के अंतराल में 'एसक्लड पर निर्भरता' द्वारा निर्धारित जीवनकाल नहीं है। इसका मतलब यह है कि जब तक आप उन्हें मजबूती से साफ नहीं करते हैं तब तक वे डेटाबेस में होंगे। लेख के मुताबिक http://rusanu.com/2014/03/31/how-to-prevent-conversation-endpoint-leaks/ (अंत में) पुराने वार्तालाप अंतराल को साफ करने का यह सही तरीका है। – dyatchenko

+0

इसका मतलब यह है कि यदि मैं इस एसक्यूएल 'WHERE CEP.state =' DI 'या CEP.state =' CD'' का उपयोग करता हूं तो पुरानी बातचीत हटा दी जाएगी? – Mou

0

मैं बिल्कुल वैसा ही समस्या का सामना कर रहा हूँ। मैं डेटा एक्सेस घटक बना रहा हूं जो SQL सर्वर 2005 डेटाबेस से कुछ प्रश्नों को कैश कर रहा है। इस चमकदार नए का उपयोग करके कैश को अमान्य कर दिया गया है, अब अच्छी तरह से नया नहीं है, एसक्यूएल पर निर्भरता दृष्टिकोण।

क्योंकि इस घटक का उपयोग एएसपी.नेट के साथ-साथ फॉर्म और विंडोज सर्विस अनुप्रयोगों में भी किया जाएगा, मैं (आंतरिक रूप से) SqlDependency.Stop() को एक आम तरीका खोज रहा हूं।

एक finalizer का उपयोग करना मेरा पहला विचार भी था, और इस बाहर काम नहीं किया। मेरी दूसरी कोशिश AppDomain.DomainUnload के लिए इवेंट हैंडलर का उपयोग कर रही थी।

आखिरकार, यह काम करता प्रतीत होता है ... लेकिन वीएस 2005 में अंतर्निर्मित वेबसर्वर 100% CPU के साथ 4-5 मिनट तक लटकाएगा जबकि SqlDependy.Stop() से बाहर निकलता है। असल में, मुझे अपनी मशीन (पेंटियम एम लैपटॉप) को अवरुद्ध करने वाली किसी भी अन्य प्रक्रिया को याद नहीं किया जा सकता है ताकि मैं मुश्किल से कार्य प्रबंधक ला सकूं ... मुझे उम्मीद नहीं थी कि यह उपयोगकर्ता-स्थान और यहां तक ​​कि प्रबंधित कोड से भी संभव था इस समय के दौरान (SQL सर्वर एक और बॉक्स पर चल रहा है।), यहां तक ​​कि प्रदर्शन मॉनिटर कुछ भी लॉग इन करने के लिए मना कर दिया, तो मैं यह नहीं कह सकते कि क्या विंडोज का एक बहुत संभालती है या .NET अपवाद envolved या जो कुछ भी कर रहे हैं ...

Application_End ईवेंट से इसे कॉल करना ठीक काम करता है (और केवल कुछ मिलीसेकंड लेता है), हालांकि यह ASP.NET के लिए विशिष्ट है।

कोई भी विचार

+0

मैं सेवा दलाल का उपयोग करने पर छोड़ दिया। मैं यह समझने में सक्षम नहीं था कि रिसाव क्या हो रहा था। – JeremyK

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