2012-02-24 1 views
15

Я работаю с SQLDependency, чтобы уведомить меня, если есть изменение в базе данных. После запуска программы он работает отлично. Когда я делаю первое изменение, событие срабатывает. Wohoo ... это здорово. Но если я сделал второе изменение, событие не срабатывает снова. Я искал всю сеть, я думаю, но ничего не нашел об этой проблеме. Только обнаруженные проблемы, когда событие OnChange запускается в цикле. Может ли кто-нибудь мне помочь?SQLDependency_OnChange-Event срабатывает только один раз

Вот маленький кусок кода:

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

мой OnChange-событие выглядит следующим образом:

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 
    } 

Где проблема?

+0

вам необходимо инициировать SqlDependency снова после первого вызова события. поэтому он не сломается для 2-го события и так далее. он будет работать отлично. – adnan

ответ

2

Не уверен, если это ваша проблема, но вы располагаете команду сразу после того, как вы его создал:

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

Это выглядит как ошибка.

+0

Этот код примера Microsoft делает то же самое. Я пробовал оба способа, и событие все еще только срабатывает один раз. – BlueMonkMN

8

Я тоже сталкивался с этой проблемой. Вам нужно создать новый объект SqlDependency (после отмены подписки на существующий из события OnChange), а затем запустить новую команду ExecuteReader. Я получил эту идею из этого поста:

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

Это обычно имеет смысл, так как только вы получили уведомление об изменении обычно вы хотите повторно запрашивать данные.

1

Посмотрите мой друг:

dep.OnChange -= this.dep_OnChange; 

вы отмените произвели свое мероприятие; что неверно; просто удалите эту строку;

+2

Ему нужно это сделать, потому что новая зависимость должна создаваться каждый раз. Это одноразовое событие. – Marshal

0

В GetStates():

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

эти линии должны быть выполнены только при регистрации зависимость SQL для впервые.

Ограничьте их, когда вы вызываете метод из события OnChange.

3

В вашем методе private void dep_OnChange(object sender, SqlNotificationEventArgs e) после отмены подписки dep_OnChange события вы должны вызвать private void GetStates() снова, снова инициализировать dep.OnChange события.