2012-02-24 22 views
15

Sto lavorando con SQLDependency per notificarmi se c'è una modifica nel Database. Dopo l'avvio del programma funziona perfettamente. Quando faccio un primo cambio, l'evento si accende. Wohoo ... è fantastico. Ma se ho fatto una seconda modifica, l'evento non si attiva di nuovo. Ho cercato tutto il web, ma non ho trovato nulla su questo problema. Trovato solo problemi in cui l'evento OnChange si attiva in un loop. Qualcuno può aiutarmi?SQLDependency_OnChange-Event scatta solo una volta.

Ecco un piccolo pezzo di codice:

private void GetStates() 
    { 
     if (!DoesUserHavePermission()) 
      return; 

     SqlDependency.Stop(con); 
     SqlDependency.Start(con); 

     using (SqlConnection cn = new SqlConnection(con)) 
     { 
      using (SqlCommand cmd = cn.CreateCommand()) 
      { 
       cmd.CommandType = CommandType.Text; 
       cmd.CommandText = "SELECT Bla, Bla2, ..FROM dbo.[BLA3]" 

       cmd.Notification = null; 
       cmd.Dispose(); 

       SqlDependency dep = new SqlDependency(cmd); 
       dep.OnChange += new OnChangeEventHandler(dep_OnChange); 

       cn.Open(); 

       using (SqlDataReader dr = cmd.ExecuteReader()) 
       { 
        state.Clear(); //In this Case "state" is a List<string> 
        while (dr.Read()) 
        { 
         state.Add(dr.GetString(0) + "|" + dr.GetInt32(3)); 
        } 
        dr.Dispose(); 
        dr.Close(); 
       }      
      } 
     } 
    } 

mia OnChange-evento è simile al seguente:

private void dep_OnChange(object sender, SqlNotificationEventArgs e) 
    { 
     SqlDependency dep = sender as SqlDependency; 
     dep.OnChange -= this.dep_OnChange; 

     using (SqlConnection cn = new SqlConnection(con)) 
     { 
      using (SqlCommand cmd = cn.CreateCommand()) 
      { 
       cmd.CommandType = CommandType.Text; 
       cmd.CommandText = "SELECT Bla, Bla2, ..FROM dbo.[BLA3]"; 

       cmd.Notification = null; 

       if (e.Type == SqlNotificationType.Change) 
       { 
        if (cn.State != ConnectionState.Open) 
        { 
         cn.Open(); 
        } 

        using (SqlDataReader dr = cmd.ExecuteReader()) 
        { 
         state.Clear(); // Clear and Refill the stringlist "state" 
         while (dr.Read()) 
         { 
          state.Add(dr.GetString(0) + "|" + dr.GetInt32(3)); 
         } 
        } 
       } 
       cn.Close(); 
      } 
     } 
     this.GetStates(); //to go ahead and wait for a new change 
    } 

Dov'è il problema?

+0

è necessario avviare nuovamente SqlDependency dopo la chiamata di evento 1a volta. quindi non si romperà per il 2 ° evento e così via. funzionerà perfettamente. – adnan

risposta

2

Non sono sicuro se questo è il vostro problema, ma di smaltire il comando subito dopo averla creata:

using (SqlCommand cmd = cn.CreateCommand()) 
{ 
    ... 
    cmd.Dispose(); 

Sembra un insetto.

+0

Quel codice di esempio Microsoft fa la stessa cosa. Ho provato entrambi i modi, e l'evento sembra solo sparare una volta sola. – BlueMonkMN

8

Ho riscontrato anche questo problema. È necessario creare una nuova entità SqlDependency (dopo aver annullato la sottoscrizione di quello esistente dall'evento OnChange) e quindi eseguire un nuovo comando ExecuteReader. Ho avuto l'idea da questo post:

http://www.codeproject.com/Articles/12335/Using-SqlDependency-for-data-change-events

Questo fa di solito senso, come una volta venuti a conoscenza di un cambiamento è di norma vuole ri-query i dati.

1

Guarda il mio amico:

dep.OnChange -= this.dep_OnChange; 

un-licenziato il vostro evento; che non è vero; elimina questa riga;

+2

Ha bisogno di farlo, perché una nuova dipendenza deve essere creata ogni volta. Questo è un evento che cambia una volta sola. – Marshal

0

In GetStates():

SqlDependency.Stop(con); SqlDependency.Start(con);

queste linee devono essere eseguiti solo quando si registra la dipendenza SQL per prima volta.

Limita loro quando chiami il metodo dall'evento OnChange.

3

Nel metodo private void dep_OnChange(object sender, SqlNotificationEventArgs e) dopo aver annullato l'iscrizione all'evento dep_OnChange, è necessario chiamare nuovamente lo private void GetStates() per inizializzare nuovamente l'evento dep.OnChange.