简体   繁体   中英

SqlDependency is working with one but not with other table

I have written this class to automate 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;
        }
    }
}

in my program I use this Class like that:

   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();

Now my Problem is that when I change anything in table2 I do not get a notification, but when I do the same for table 1 I get a notification!

any ideas what the problem could be? I also tried to only suscribe for table2...but it remain the same.

I've repeated your situation and wrote unit test (TwoTablesNotificationTest), but didn't find anything. It works fine for me. In this situation you could stop receive notifications from SqlDependency in case of destructor call of some DatabaseChangeAlert entity, because it has SqlDependency.Stop(connectionString) instruction. Thus, you have to call SqlDependency.Start after every SqlDependency.Stop to continue receiving events, but destructor is called automatically by garbage collector from parallel thread and it may cause this effect.

And I want to warn you - be careful using SqlDependency class because it has memory leak problem . For my project I used open source realization of SqlDependency - SqlDependencyEx . It is very easy to use:

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

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM