2013-12-10 7 views
8

Ho il seguente codice che utilizza SqlDependency per monitorare i cambiamenti in una delle mie basi di dati E le grandi opere, ad eccezione di ogni corsa si genera il proprio coda/servizio/percorso con un GUID nel database:Utilizzando SqlDependency con code di nome

Classe:

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"); 
    } 
} 

Esecuzione:

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(); 
} 

Invece di generare un proprio ogni volta coda/servizio/percorso, vorrei creare loro davanti e poi dire la mia pro grammo per usarli.

sono andato avanti e ha creato questi oggetti sul database:

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

e modificato il mio codice C# per utilizzare questa coda e servizio:

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

Fare questi codice cambia cause niente code ad essere creato al volo quando eseguo il mio codice, tuttavia il mio codice non funziona più e la mia app non riconosce le modifiche apportate alla mia tabella/query.

Ho passato giorni cercando di capirlo senza successo, qualcuno può offrire qualche consiglio? Grazie.

+0

Grazie al codice nella tua domanda sono finalmente riuscito a impostare SqlDependency con successo ... Fino ad ora ho continuato a ricevere errori molto criptici (o nessun errore, tutto il resto non funzionava). Mi chiedo perché sia ​​così difficile trovare qualche buon esempio su questo ... Comunque, grazie! – LambdaCruiser

risposta

6

Calcolato - l'errore era nelle istruzioni SQL CREATE. Stavo usando:

CREATE SERVICE NamesService ON QUEUE NamesQueue; 

ma secondo http://technet.microsoft.com/en-us/library/ms190332.aspx, il comando CREATE SERVICE ha bisogno di prendere un parametro CONTRACT_NAME al fine di essere in grado di permette altre finestre di dialogo di indirizzare il servizio in fase di creazione.

Quindi, utilizzando l'istruzione CREATE sotto risolto il mio problema:

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

Fare attenzione usando SqlDependency classe - ha il problems con perdite di memoria. Hovewer, puoi utilizzare una realizzazione open source della classe SqlDependency - SqlDependencyEx. Utilizza un trigger del database e una notifica nativa di Service Broker per ricevere eventi relativi alle modifiche della tabella. Questo è un esempio di utilizzo:

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); 

Spero che questo aiuti.

Problemi correlati