SQLDependency_OnChange-Event仅触发一次Time

我正在使用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 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 } 

问题出在哪儿?

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

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

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

在取消订阅dep_OnChange事件后private void dep_OnChange(object sender, SqlNotificationEventArgs e)private void dep_OnChange(object sender, SqlNotificationEventArgs e)方法中,应再次调用private void GetStates() ,以再次初始化dep.OnChange事件。

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

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

它看起来像一个bug。

看我的朋友:

 dep.OnChange -= this.dep_OnChange; 

你解雇了你的活动; 这不是真的; 只需删除此行;

在GetStates()中:

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

只有在第一次注册sql依赖项时才应执行这些行。

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

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

以下代码对我有用。

 class Program { static string connectionString = "Server=.;Database=test_sql_dependency;Integrated Security=True;"; static void Main(string[] args) { // 1. create database // 2. enable service broker by executing this sql command on the database. // alter database test_sql_dependency set enable_broker // 3. start sql dependency, for some sql server connection string or with queue if you want. //var queueName = "myFirstQueue"; //SqlDependency.Start(connectionString, queueName); SqlDependency.Start(connectionString); // complete the rest of the steps in seperate method to be able to call it again when you need to // re-subscribe to the event again, becuase by default it will be executed only one time RegisterSqlDependency(); Console.WriteLine("Listening to database changes..."); Console.ReadLine(); } static void RegisterSqlDependency() { using (SqlConnection connection = new SqlConnection(connectionString)) { if (connection.State != System.Data.ConnectionState.Open) { connection.Open(); } // 4. create a sql command // you can't say select *, and also you have to specefy the db owner (dbo.) SqlCommand command = new SqlCommand("select Id, Name from dbo.Employee", connection); // 5. create dependency and associtate it to the sql command SqlDependency dependency = new SqlDependency(command); // 6. subscribe to sql dependency event dependency.OnChange += new OnChangeEventHandler(OnDependencyChange); // 7. execute the command using (SqlDataReader reader = command.ExecuteReader()) { } } } static void OnDependencyChange(object sender, SqlNotificationEventArgs e) { var InsertOrUpdateOrDelte = e.Info; //-----------------------------Finally------------------------- // after you knew that there is a change happened // you have to unsubscribe the event and execute the command again and then re-subscribe to the event // 1. unsubscribe the event SqlDependency dependency = sender as SqlDependency; dependency.OnChange -= OnDependencyChange; // 2. re-subscribe to the event and execute the command again RegisterSqlDependency(); } }