Piero Alberto
Piero Alberto

Reputation: 3943

SqlDependency doesn't fire/trigger event

I have followed some tutorial to send notification to my app when something changes in a table in my SQL Server database. This is my listener class:

class dbListener
{
    public dbListener() 
    {
        Debug.WriteLine(MainWindow.dbContext.Database.Connection.ConnectionString + "Password=xxx;");

        SqlDependency.Stop(MainWindow.dbContext.Database.Connection.ConnectionString + "Password=xxx;");
        SqlDependency.Start(MainWindow.dbContext.Database.Connection.ConnectionString + "Password=xxx;");
        connection = new SqlConnection(MainWindow.dbContext.Database.Connection.ConnectionString + "Password=xxx;");
        connection.Open();
        SomeMethod();
    }
    SqlConnection connection;
    void SomeMethod()
    {
        // Assume connection is an open SqlConnection.
        // Create a new SqlCommand object.

        SqlCommand command = new SqlCommand("SELECT CODVEI FROM dbo.ArchivioErogazioni", connection);
        // Create a dependency and associate it with the SqlCommand.
        command.Notification = null;  // ---> DO I NEED IT??
        SqlDependency dependency = new SqlDependency(command);
        // Maintain the refence in a class member.
        // Subscribe to the SqlDependency event.
        dependency.OnChange += new OnChangeEventHandler(OnDependencyChange);
        // Execute the command.
        command.ExecuteReader();
    }
    // Handler method
    void OnDependencyChange(object sender, SqlNotificationEventArgs e)
    {
        // Handle the event (for example, invalidate this cache entry).
        MessageBox.Show("ikjkjkj");
        Debug.WriteLine("fkldjkfjklgjf");
        SomeMethod();
    }

    void Termination()
    {
        // Release the dependency.
        SqlDependency.Stop(MainWindow.GetConnectionString("Model"));
    }
}

It doesn't fire the event correctly. At the start of the app, it shows me the message box (it is in the event management to test it) once or twice, I don't know why. Then, when I edit the values in the database from SQL Server Management Studio, I get the message box or 0 or 1 or 2 times, then it never fires again.

In my database, I have execute this script:

USE master ;
GO
ALTER DATABASE IN4MATICSystem_Pie SET ENABLE_BROKER WITH ROLLBACK IMMEDIATE
GO
ALTER AUTHORIZATION ON DATABASE::IN4MATICSystem_Pie to sa;

I have surely done a big mistake..... which one??

UPDATE:

After the hints of T McKeown, this is my code (still not working, it shows me 2 or 3 message boxes at startup and then nothing):

class dbListener
{
    public dbListener() 
    {
        Debug.WriteLine(MainWindow.dbContext.Database.Connection.ConnectionString + "Password=xxx;");

        SqlDependency.Stop(MainWindow.dbContext.Database.Connection.ConnectionString + "Password=xxx;");
        SqlDependency.Start(MainWindow.dbContext.Database.Connection.ConnectionString + "Password=xxx;");
        connection = new SqlConnection(MainWindow.dbContext.Database.Connection.ConnectionString + "Password=xxx;");
        connection.Open();
        SomeMethod();
    }
    SqlConnection connection;

    SqlCommand command;
    void SomeMethod()
    {
        // Assume connection is an open SqlConnection.
        // Create a new SqlCommand object.

        if (command == null)
        {
            command = new SqlCommand("SELECT * FROM dbo.ArchivioErogazioni", connection);
            // Create a dependency and associate it with the SqlCommand.
        }
        else
        {
            command.Notification = null;  // this cancels any previous notifcation object
        }
        SqlDependency dependency = new SqlDependency(command);
        // Maintain the refence in a class member.
        // Subscribe to the SqlDependency event.
        dependency.OnChange += new OnChangeEventHandler(OnDependencyChange);
        // Execute the command.
        command.ExecuteReader();
    }
    // Handler method
    void OnDependencyChange(object sender, SqlNotificationEventArgs e)
    {
        if (e.Type == SqlNotificationType.Change) 
        { 
            // Handle the event (for example, invalidate this cache entry).
            MessageBox.Show("ikjkjkj");
            Debug.WriteLine("fkldjkfjklgjf");
            SqlDependency dependency = (SqlDependency)sender;
            dependency.OnChange -= OnDependencyChange; 
            //dependency.OnChange -= OnDependencyChange;
            SomeMethod();
        }
    }

    void Termination()
    {
        // Release the dependency.
        SqlDependency.Stop(MainWindow.GetConnectionString("Model"));
        connection.Close();
    }
}

Upvotes: 0

Views: 2430

Answers (1)

T McKeown
T McKeown

Reputation: 12857

Try this:

void OnDependencyChange(object sender, SqlNotificationEventArgs e)
{
    // Handle the event (for example, invalidate this cache entry).
    MessageBox.Show("ikjkjkj");
    Debug.WriteLine("fkldjkfjklgjf");

   SqlDependency dependency =
    (SqlDependency)sender;
    dependency.OnChange -= OnDependencyChange;
    SomeMethod(); //re-register
}

Modify SomeMethod():

SqlConnection connection;
SqlCommand command;   <-- make command instance var

void SomeMethod()
{
    // Assume connection is an open SqlConnection.
    // Create a new SqlCommand object.

    if ( command == null )
    {
       command = new SqlCommand("SELECT * FROM dbo.ArchivioErogazioni", connection);
      // Create a dependency and associate it with the SqlCommand.
    }
    else{
       command.Notification = null;  // this cancels any previous notifcation object
    }
    SqlDependency dependency = new SqlDependency(command);
    // Maintain the refence in a class member.
    // Subscribe to the SqlDependency event.
    dependency.OnChange += new OnChangeEventHandler(OnDependencyChange);
    // Execute the command.
    command.ExecuteReader();
}

Call this function, does it return true?

private bool CanRequestNotifications()
{
// In order to use the callback feature of the
// SqlDependency, the application must have
// the SqlClientPermission permission.
try
{
    SqlClientPermission perm =
        new SqlClientPermission(
        PermissionState.Unrestricted);

    perm.Demand();

    return true;
}
catch
{
    return false;
}
}

Upvotes: 1

Related Questions