2012-02-24 16 views
15

Pracuję z SQLDependency, aby powiadomić mnie, jeśli nastąpiła zmiana w bazie danych. Po uruchomieniu programu działa dobrze. Kiedy dokonam pierwszej zmiany, Zdarzenie zostanie wywołane. Wohoo ... to świetnie. Ale jeśli dokonałem drugiej zmiany, zdarzenie nie zostanie ponownie uruchomione. Przeszukałem całą sieć, ale myślę, że nie znalazłem nic na temat tego problemu. Występują tylko problemy związane z uruchomieniem zdarzenia OnChange-Event w pętli. Czy ktoś może mi pomóc?SQLDependency_OnChange-Event uruchamia tylko jeden czas.

Oto mały kawałek kodu:

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

mój OnChange-Event wygląda następująco:

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 
    } 

Gdzie jest problem?

+0

musisz ponownie zainicjować SqlDependency po pierwszym zdarzeniu. więc nie zostanie przerwane na drugie wydarzenie i tak dalej. to zadziała idealnie. – adnan

Odpowiedz

2

Nie wiem, czy to jest twój problem, ale pozbyciem polecenie tuż po tym, jak go przygotować:

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

wygląda jak robaka.

+0

Ten przykładowy kod Microsoft robi to samo. Próbowałem obu sposobów, a wydarzenie wciąż wydaje się tylko raz. – BlueMonkMN

1

Spójrz przyjacielu:

dep.OnChange -= this.dep_OnChange; 

ty un opalanych wydarzenie; co nie jest prawdą; po prostu usuń ten wiersz;

+2

Musi to zrobić, ponieważ za każdym razem ma powstać nowa zależność. To jednorazowa zmiana. – Marshal

0

W GetStates():

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

linie te powinny być wykonywane tylko przy rejestracji zależność SQL dla raz pierwszy.

Ogranicz je, wywołując metodę ze zdarzenia OnChange.

3

Po zrezygnowaniu z subskrypcji private void dep_OnChange(object sender, SqlNotificationEventArgs e) należy ponownie wywołać , aby ponownie zainicjować zdarzenie dep.OnChange.