SqlDependency 正在使用一个但不与其他 table

SqlDependency is working with one but not with other table

我写了这个 class 来自动化 SQLDependency

public class DatabaseChangeAlert
{
    private String connectionString;
    private SqlConnection sc;
    public event EventHandler<DatabaseChangedEvent> DatabaseChangeEvent;
    private String tabelle;
    private String query;
    public DatabaseChangeAlert(String tabelle, String conString)
    {           
        try
        {
            this.tabelle = tabelle;
            this.sc = new SqlConnection(conString); ;//new SqlConnection(GlobalResources.ConnectionString);
            this.connectionString = conString;
            String sel = "";
            using (SqlConnection con = new SqlConnection(conString))
            {
                con.Open();
                SqlCommand cmd = con.CreateCommand();
                cmd.CommandText = "SELECT dbo.syscolumns.name AS Spaltenname " +
                        " FROM dbo.syscolumns INNER JOIN  " +
                        " dbo.sysobjects ON dbo.syscolumns.id = dbo.sysobjects.id " +
                        " WHERE (dbo.sysobjects.xtype = 'U') and dbo.sysobjects.name='" + tabelle + "' ";

                using (SqlDataReader sr = cmd.ExecuteReader())
                {
                    while (sr.Read())
                    {
                        sel += "["+sr.GetString(0)+"],";
                    }

                }
                sel = sel.Substring(0, sel.Length - 1);
            }
            query = "SELECT " + sel + " from [dbo].[" + tabelle+"]";
        }
        catch (Exception ex) { }
    }
    ~DatabaseChangeAlert()
    {
        if(connectionString!=null)
        SqlDependency.Stop(connectionString);
    }
    public void start()
    {
        try
        {
            SqlDependency.Start(connectionString);
        }
        catch (Exception ex)
        {
            //                log(ex)
        }

        try
        {
            startDependency();
        }
        catch (Exception ex)
        {
//                log(ex)
        }
    }
    private void startDependency()
    {            
        // Assume connection is an open SqlConnection.
        // Create a new SqlCommand object.
        using (SqlCommand command = new SqlCommand(query, sc))
        {
            sc.Open();
            // Create a dependency and associate it with the SqlCommand.
            SqlDependency dependency = new SqlDependency(command);
            // Maintain the refence in a class member.

            // Subscribe to the SqlDependency event.
            dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
            // Execute the command.
            using (SqlDataReader reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                }
            }
            sc.Close();
        }
    }

    void dependency_OnChange(object sender, SqlNotificationEventArgs e)
    {           
        if (e.Info != SqlNotificationInfo.Invalid)
        {
            startDependency();

            if (DatabaseChangeEvent != null)
            {
                DatabaseChangeEvent(this, new DatabaseChangedEvent(tabelle,e.Info));
            }
        }
    }

    public class DatabaseChangedEvent : EventArgs
    {
        public readonly String Tablename;
        public readonly SqlNotificationInfo info;
        public DatabaseChangedEvent(String tablename,SqlNotificationInfo info)
        {
            this.Tablename = tablename;
            this.info = info;
        }
    }
}

在我的程序中,我这样使用 Class:

   DatabaseChangeAlert alerttz = new DatabaseChangeAlert("table1", GlobalResources.ConnectionString);
        alerttz.DatabaseChangeEvent += (e,d)=>{
            MessageBox.Show("table1 changed");
        };
        alerttz.start();

        DatabaseChangeAlert alert = new DatabaseChangeAlert("table2", GlobalResources.ConnectionString);
        alert.DatabaseChangeEvent += (e, d) =>
        {
            MessageBox.Show("table2 changed");
        };
        alert.start();

现在我的问题是,当我更改 table2 中的任何内容时,我没有收到通知,但是当我对 table1 执行相同操作时,我会收到通知!

知道问题出在哪里吗? 我也尝试只订阅 table2...但它保持不变。

我重复了你的情况并写了 unit test (TwoTablesNotificationTest),但没有找到任何东西。这对我来说可以。在这种情况下,如果某些 DatabaseChangeAlert 实体的析构函数调用,您可以停止从 SqlDependency 接收通知,因为它有 SqlDependency.Stop(connectionString) 指令。因此,您必须在每个 SqlDependency.Stop 之后调用 SqlDependency.Start 才能继续接收事件,但是析构函数是由并行线程的垃圾收集器自动调用的,它可能会导致这种情况。

我想警告你 - 使用 SqlDependency class 时要小心,因为它有 memory leak problem. For my project I used open source realization of SqlDependency - SqlDependencyEx。使用起来非常简单:

int changesReceived = 0;
using (SqlDependencyEx sqlDependency = new SqlDependencyEx(
          TEST_CONNECTION_STRING, TEST_DATABASE_NAME, TEST_TABLE_NAME)) 
{
    sqlDependency.TableChanged += (o, e) => changesReceived++;
    sqlDependency.Start();

    // Make table changes.
    MakeTableInsertDeleteChanges(changesCount);

    // Wait a little bit to receive all changes.
    Thread.Sleep(1000);
}

Assert.AreEqual(changesCount, changesReceived);

希望对您有所帮助。