SqlDependency onchange 为每个浏览器实例触发多次

SqlDependency onchange fires multiple times for each browser instance

对于重复的问题深表歉意。我用谷歌搜索,到处都只找到问题,但没有成功的解决方案。我面临着与 here and here 描述的完全相同的问题,并且在过去一周一直在苦苦挣扎,但我没有找到任何成功,所以最后我决定在这里问一个问题。我试图按照这些问题中建议的评论自己解决它,但成功了。我希望 SqlDependency onchange 事件针对任何数量的实例或登录的用户恰好触发一次。

每当新用户登录到应用程序时调用一次此方法

 public List<TransactionMaster> GetUnregisteredTransactions()
    {
        List<TransactionMaster> ltrans = new List<TransactionMaster>();
        TransactionMaster trans = new TransactionMaster();

        using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
        {
            string query = "SELECT TransId,  ReceivedFrom,ReceivedOn,Mask FROM [dbo].TransactionMaster  WHERE StageId =1";
            SqlDependency.Start(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString);
            using (SqlCommand cmd = new SqlCommand(query, connection))
            {
                cmd.Notification = null;
                DataTable dt = new DataTable();

                SqlDependency dependency = new SqlDependency(cmd);
                dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
                if (connection.State == ConnectionState.Closed)
                    connection.Open();
                SqlDataAdapter adapter = new SqlDataAdapter(cmd);
                adapter.Fill(dt);
                ltrans = dal.ConvertDataTable<TransactionMaster>(dt);
            }
        }
        return ltrans;
    }

然后再次从 onchange 事件调用此方法

 private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
    {
        if (e.Type == SqlNotificationType.Change)
            TransactionHub.GetUnregTransactions(GetUnregisteredTransactions());

    }

每次调用 GetUnregisteredTransactions 时都会调用 dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);,这会导致注册一个新事件,因此现在有两个事件将触发。当这两个事件触发时,它将再调用 dependency.OnChange += new OnChangeEventHandler(dependency_OnChange); 两次,使其成为将触发的 4 个事件。每次调用时,这个数字都会加倍,直到 dependency 指向的对象被垃圾回收。

您需要不重新注册对来自事件版本的调用的依赖(例如将 bool 传递给函数以了解它是否应该进行注册)或者您需要注销创建新通知之前的旧通知。

这里是一个注销的例子。

private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
    SqlDependency dependency = (SqlDependency)sender;
    dependency.OnChange -= new OnChangeEventHandler(dependency_OnChange);

    if (e.Type == SqlNotificationType.Change)
        TransactionHub.GetUnregTransactions(GetUnregisteredTransactions());

}

对于我的案例,每次触发事件时,我都会将事件添加到依赖项中

 dependency.OnChange += new OnChangeEventHandler(SqlNotification.dependency_OnChange);

找到 this solution 后,我将代码更改为:

 dependency.OnChange -= new OnChangeEventHandler(SqlNotification.dependency_OnChange);
 dependency.OnChange += new OnChangeEventHandler(SqlNotification.dependency_OnChange);

这解决了我的问题。