27

SQLDependencyを使用して、データベースに変更があった場合に通知します。プログラムの起動後は問題なく動作します。最初の変更を行うと、イベントが発生します。うわー...それは素晴らしい。しかし、2回目の変更を行っても、イベントは再度発生しません。私は思うすべてのウェブを検索しましたが、この問題については何も見つかりませんでした。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-Eventは次のようになります。

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
    }

問題はどこだ?

4

6 に答える 6

13

私もこの問題に遭遇していました。新しい SqlDependency エンティティを作成し (既存のエンティティを OnChange イベントからサブスクライブ解除した後)、新しい ExecuteReader コマンドを実行する必要があります。この投稿からアイデアを得ました:

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

変更の通知を受け取ると、通常はデータを再クエリする必要があるため、これは通常は理にかなっています。

于 2013-03-20T20:52:21.547 に答える
3

イベントのサブスクライブを解除した後のprivate void dep_OnChange(object sender, SqlNotificationEventArgs e)メソッドで、もう一度dep_OnChangeを呼び出してprivate void GetStates()、イベントを再度初期化する必要がありますdep.OnChange

于 2015-04-10T17:18:27.417 に答える
1

それが問題かどうかはわかりませんが、コマンドを作成した直後に破棄します。

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

バグのようです。

于 2012-02-24T15:34:06.347 に答える