2013-12-10 4 views
8

मैं है निम्नलिखित कोड मेरे डेटाबेस में से एक में परिवर्तन नजर रखने के लिए यह बहुत अच्छा काम करता है, हर इसे चलाने को छोड़कर SqlDependency का उपयोग करता है डेटाबेस में एक guid के साथ अपने स्वयं कतार/सेवा/रूट उत्पन्न करता है:का उपयोग SqlDependency

कक्षा:

class SqlWatcher 
{ 
    private string connectionString; 
    private string sqlQueue; 
    private string listenerQuery; 
    private SqlDependency dependency; 

    public SqlWatcher(string connectionString, string sqlQueue, string listenerQuery) 
    { 
     this.connectionString = connectionString; 
     this.sqlQueue = sqlQueue; 
     this.listenerQuery = listenerQuery; 
     this.dependency = null; 
    } 

    public void Start() 
    { 
     SqlDependency.Start(connectionString); 
     ListenForChanges(); 
    } 

    public void Stop() 
    { 
     SqlDependency.Stop(this.connectionString); 
    } 

    private void ListenForChanges() 
    { 
     //Remove existing dependency, if necessary 
     if (dependency != null) 
     { 
      dependency.OnChange -= onDependencyChange; 
      dependency = null; 
     } 

     SqlConnection connection = new SqlConnection(connectionString); 
     connection.Open(); 

     SqlCommand command = new SqlCommand(listenerQuery, connection); 

     dependency = new SqlDependency(command); 

     // Subscribe to the SqlDependency event. 
     dependency.OnChange += new OnChangeEventHandler(onDependencyChange); 

     SqlDependency.Start(connectionString); 

     command.ExecuteReader(); 

     //Perform this action when SQL notifies of a change 
     performAction(); 

     connection.Close(); 
    } 

    private void onDependencyChange(Object o, SqlNotificationEventArgs args) 
    { 
     if ((args.Source.ToString() == "Data") || (args.Source.ToString() == "Timeout")) 
     { 
      Console.WriteLine(System.Environment.NewLine + "Refreshing data due to {0}", args.Source); 
      ListenForChanges(); 
     } 
     else 
     { 
      Console.WriteLine(System.Environment.NewLine + "Data not refreshed due to unexpected SqlNotificationEventArgs: Source={0}, Info={1}, Type={2}", args.Source, args.Info, args.Type.ToString()); 
     } 
    } 

    private void performAction() 
    { 
     Console.WriteLine("Performing action"); 
    } 
} 

निष्पादन:

static void Main(string[] args) 
{ 
    string connectionString = @"<MY CONNECTION STRING>"; 
    string sqlQueue = @"NamesQueue"; 

    //Listener query restrictions: http://msdn.microsoft.com/en-us/library/aewzkxxh.aspx 
    string listenerQuery = "SELECT Value FROM dbo.Table WHERE Name = 'Test'"; 

    SqlWatcher w = new SqlWatcher(connectionString, sqlQueue, listenerQuery); 
    w.Start(); 
    Thread.Sleep(10000); 
    w.Stop(); 
} 

के बजाय अपनी ही कतार/सेवा/मार्ग हर पैदा करने, मैं उन्हें सामने बनाना चाहेंगे और फिर मेरी समर्थक बता उनका उपयोग करने के लिए ग्राम।

मैं आगे चला गया और डेटाबेस पर इन वस्तुओं बनाया:

CREATE QUEUE NamesQueue; 
CREATE SERVICE NamesService ON QUEUE NamesQueue; 
CREATE ROUTE NamesRoute WITH SERVICE_NAME = 'NamesService', ADDRESS = 'LOCAL'; 

और इस कतार और सेवा का उपयोग करने के लिए अपने सी # कोड संशोधित:

... 
SqlDependency.Start(connectionString, sqlQueue); 
... 
SqlDependency.Stop(this.connectionString, sqlQueue); 
... 
dependency = new SqlDependency(command, "service=NamesService;local database=<MY DB>", 0); 
... 
SqlDependency.Start(connectionString,sqlQueue); 
... 

इन कोड में परिवर्तन का कारण बनता है कोई कतार होने के लिए बनाना जब मैं अपना कोड चलाता हूं तो ऑन-द-फ्लाई बनाया जाता है, हालांकि मेरा कोड अब काम नहीं करता है और मेरा ऐप मेरी तालिका/क्वेरी में किए गए परिवर्तनों को नहीं पहचानता है।

मैंने इसे बिना किसी सफलता के समझने के लिए दिन बिताए हैं, क्या कोई सलाह दे सकता है? धन्यवाद।

+0

आपके प्रश्न में कोड के लिए धन्यवाद, मैं अंत में सफलतापूर्वक एसक्यूएल पर निर्भरता स्थापित करने में सक्षम हूं ... अब तक मुझे बहुत ही गुप्त त्रुटियां मिल रही हैं (या बिल्कुल कोई त्रुटि नहीं, केवल पूरी चीज काम नहीं कर रही है)। मुझे आश्चर्य है कि इस बारे में कोई अच्छा उदाहरण क्यों खोजना मुश्किल है ... वैसे भी, धन्यवाद! – LambdaCruiser

उत्तर

6

यह पता लगाया - त्रुटि मेरे SQL CREATE स्टेटमेंट में थी। मैं उपयोग कर रहा था:

CREATE SERVICE NamesService ON QUEUE NamesQueue; 

लेकिन http://technet.microsoft.com/en-us/library/ms190332.aspx के अनुसार, बनाएँ सेवा आदेश के क्रम में एक CONTRACT_NAME पैरामीटर लेने के लिए करने में सक्षम होने की जरूरत है अन्य संवादों को लक्षित करने के सेवा बनाया जा रहा है।

तो, का उपयोग कर नीचे बनाएं बयान मेरी समस्या का समाधान हो:

CREATE SERVICE NamesService 
ON QUEUE NamesQueue 
([http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification]) ; 
0

SqlDependency वर्ग का उपयोग कर सावधान रहें - यह मेमोरी लीक साथ problems है। होवर, आप 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); 

आशा है कि इससे मदद मिलती है।

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