SQLDependency_OnChange-Event仅触发一次

时间:2012-02-24 12:36:46

标签: c# wpf sqldependency

我正在使用SQLDependency来通知我数据库是否有变化。 程序启动后,它工作得很好。当我进行第一次更改时,事件会触发。 Wohoo ......太好了。 但如果我做了第二次更改,事件就不再发生了。我搜索了所有网络,但我没有发现任何有关此问题的信息。仅发现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
    }

问题出在哪里?

6 个答案:

答案 0 :(得分:11)

我也遇到了这个问题。您需要创建一个新的SqlDependency实体(在取消订阅OnChange事件中的现有实体之后),然后运行新的ExecuteReader命令。我从这篇文章中得到了这个想法:

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

这通常是有道理的,因为一旦您收到更改通知,您通常会想要重新查询数据。

答案 1 :(得分:3)

取消订阅private void dep_OnChange(object sender, SqlNotificationEventArgs e)活动后,在dep_OnChange方法中,您应再次致电private void GetStates(),再次初始化dep.OnChange活动。

答案 2 :(得分:1)

不确定这是否是您的问题,但您在创建命令后立即处理该命令:

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

它看起来像一个bug。

答案 3 :(得分:1)

第一次更改数据库后,您必须再次执行命令并重新订阅该事件。

以下代码对我有用。

private double deg2rad(double deg)
{
    return (deg * Math.PI / 180.0);
}

private double rad2deg(double rad)
{
    return (rad * 180.0 / Math.PI);
}  

double distance(double lat1, double lon1, double lat2, double lon2)
{
    double theta = lon1 - lon2;

    double dist = Math.sin(deg2rad(lat1)) 
                    * Math.sin(deg2rad(lat2))
                    + Math.cos(deg2rad(lat1))
                    * Math.cos(deg2rad(lat2))
                    * Math.cos(deg2rad(theta));

    dist = Math.acos(dist);
    dist = rad2deg(dist);
    dist = dist * 60 * 1.1515;

    return (dist);
}

答案 4 :(得分:0)

看看我的朋友:

dep.OnChange -= this.dep_OnChange;
你取消了你的活动;这不是真的; 只需删除此行;

答案 5 :(得分:0)

在GetStates()中:

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

这些行只应在首次注册sql依赖项时执行。

从OnChange事件调用方法时限制它们。