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

时间:2015-01-28 10:08:06

标签: c# sql-server database-connection sqldependency

我已经编写了这个类来自动化SQLDependencys

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;
        }
    }
}

在我的程序中我像这样使用这个类:

   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中更改任何内容时,我没有收到通知,但是当我对表1执行相同操作时,我会收到通知!

任何想法可能是什么问题? 我也试图只为table2承诺...但它保持不变。

1 个答案:

答案 0 :(得分:1)

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

我想警告你 - 小心使用SqlDependency类,因为它有memory leak problem。对于我的项目,我使用了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);

希望这有帮助。