Hello.
I have implemented and tested a SqlDependency in a Windows Application example on MSDN: https://msdn.microsoft.com/en-us/library/a52dhwx7(v=vs.80).aspx
Unfortunately the example is not running.
I tried to set up all the necessary options on SQL Server as well which I found on:
I enclose source code for both Watcher and Updater application and also SQL Script which should enable all the necessary settings on SQL Server to allow SQL Notifications using SqlDependency.
I will be glad for any help. Is there something I missed?
Thank you very much in advance.
Best Regards,
Zdeněk Neustupa
----------------------------------- Watcher Application --------------------------------------------
public partial class MainWindow : Window { private int changeCount = 0; private const string tableName = "Technician"; private const string statusMessage = "{0} changes have occurred."; private DataSet dataToWatch = null; private SqlConnection connection = null; private SqlCommand command = null; public MainWindow() { InitializeComponent(); bGetData.IsEnabled = CanRequestNotifications(); } private bool CanRequestNotifications() { try { SqlClientPermission perm = new SqlClientPermission(PermissionState.Unrestricted); perm.Demand(); return true; } catch { return false; } } private string GetConnectionString() { return @"Server=server08\SQLSERVER2008;Database=emistar;User Id=terminal01;Password=TinT434041,;"; } private string GetSQL() { return "SELECT TechnicianName FROM Technician ORDER BY TechnicianName ASC"; } private void dependency_OnChange(object sender, SqlNotificationEventArgs e) { ISynchronizeInvoke i = (ISynchronizeInvoke)this; if (i.InvokeRequired) { OnChangeEventHandler tempDelegate = new OnChangeEventHandler(dependency_OnChange); object[] args = { sender, e }; i.BeginInvoke(tempDelegate, args); return; } SqlDependency dependency = (SqlDependency)sender; dependency.OnChange -= dependency_OnChange; ++changeCount; lChanges.Content = String.Format(statusMessage, changeCount); lbSelect.Items.Clear(); lbSelect.Items.Add("Info: " + e.Info.ToString()); lbSelect.Items.Add("Source: " + e.Source.ToString()); lbSelect.Items.Add("Type: " + e.Type.ToString()); GetData(); } private void GetData() { dataToWatch.Clear(); command.Notification = null; SqlDependency dependency = new SqlDependency(command, "Service='ChangeNotifications'", 0); dependency.OnChange += new OnChangeEventHandler(dependency_OnChange); using (SqlDataAdapter adapter = new SqlDataAdapter(command)) { adapter.Fill(dataToWatch, tableName); dgMain.ItemsSource = dataToWatch.Tables["Technician"].DefaultView; } } private void bGetData_Click(object sender, EventArgs e) { changeCount = 0; lChanges.Content = String.Format(statusMessage, changeCount); SqlDependency.Stop(GetConnectionString(), "ChangeMessages"); SqlDependency.Start(GetConnectionString(), "ChangeMessages"); if (connection == null) { connection = new SqlConnection(GetConnectionString()); } if (command == null) { command = new SqlCommand("SelectTechnicians", connection); command.CommandType = CommandType.StoredProcedure; } if (dataToWatch == null) { dataToWatch = new DataSet(); } GetData(); } }
--------------------------------------------- Updater Application --------------------------------------------------
public partial class MainWindow : Window { private SqlConnection connection = null; private SqlCommand command = null; public MainWindow() { InitializeComponent(); } private string GetConnectionString() { return @"Server=server08\SQLSERVER2008;Database=emistar;User Id=terminal01;Password=TinT434041,;"; } private string GetSQL() { return "UPDATE emistar.dbo.Technician SET TechnicianName=@TechName WHERE TechnicianID=1"; } private void bInsertClick(object sender, EventArgs e) { string techName = txtName.Text; if (connection == null) { connection = new SqlConnection(GetConnectionString()); connection.Open(); } if (command == null) { command = new SqlCommand(GetSQL(), connection); SqlParameter param = new SqlParameter("@TechName", SqlDbType.NVarChar); param.Direction = ParameterDirection.Input; param.DbType = DbType.String; command.Parameters.Add(param); } command.Parameters["@TechName"].Value = techName; int rowsAffected = command.ExecuteNonQuery(); txtName.Clear(); MessageBox.Show(rowsAffected + " records updated.", "Update"); } private void windowClosing(object sender, EventArgs e) { if (connection != null) { connection.Close(); } } }
--------------------------------------------- SQL Server Settings ---------------------------------------------
ALTER DATABASE emistar SET ENABLE_BROKER; CREATE QUEUE ChangeMessages; CREATE SERVICE ChangeNotifications ON QUEUE ChangeMessages([http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification]); --DBA creates a new role EXEC sp_addrole 'sql_dependency_subscriber' --------------------- User terminal01 ----------------------------- GRANT SUBSCRIBE QUERY NOTIFICATIONS TO terminal01 --Permission needed for startUser GRANT CREATE PROCEDURE to terminal01 GRANT CREATE QUEUE to terminal01 GRANT CREATE SERVICE to terminal01 GRANT REFERENCES on CONTRACT::[http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification] to terminal01 GRANT VIEW DEFINITION TO terminal01 --Permissions needed for executeUser GRANT SELECT to terminal01 GRANT SUBSCRIBE QUERY NOTIFICATIONS TO terminal01 GRANT RECEIVE ON QueryNotificationErrorsQueue TO terminal01 GRANT REFERENCES on CONTRACT::[http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification] to terminal01 EXEC sp_addrolemember 'sql_dependency_subscriber', 'terminal01' GRANT RECEIVE ON ChangeMessages TO terminal01; GRANT SEND ON SERVICE::ChangeNotifications TO terminal01; GRANT CREATE PROCEDURE to terminal01; GRANT CREATE QUEUE to terminal01; GRANT CREATE SERVICE to terminal01; GRANT SUBSCRIBE QUERY NOTIFICATIONS TO terminal01; GRANT INSERT ON SCHEMA::dbo TO terminal01; GRANT SELECT ON SCHEMA::dbo TO terminal01; GRANT ALTER ON SCHEMA::dbo TO terminal01; GRANT CONTROL ON SCHEMA::dbo TO terminal01; --GRANT CREATE SEQUENCE ON SCHEMA::dbo TO terminal01; GRANT DELETE ON SCHEMA::dbo TO terminal01; GRANT EXECUTE ON SCHEMA::dbo TO terminal01; GRANT INSERT ON SCHEMA::dbo TO terminal01; GRANT REFERENCES ON SCHEMA::dbo TO terminal01; GRANT SELECT ON SCHEMA::dbo TO terminal01; GRANT TAKE OWNERSHIP ON SCHEMA::dbo TO terminal01; GRANT UPDATE ON SCHEMA::dbo TO terminal01; GRANT VIEW CHANGE TRACKING ON SCHEMA::dbo TO terminal01; GRANT VIEW DEFINITION ON SCHEMA::dbo TO terminal01; --------------------- User terminal02 ----------------------------- GRANT SUBSCRIBE QUERY NOTIFICATIONS TO terminal02 --Permission needed for startUser GRANT CREATE PROCEDURE to terminal02 GRANT CREATE QUEUE to terminal02 GRANT CREATE SERVICE to terminal02 GRANT REFERENCES on CONTRACT::[http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification] to terminal02 GRANT VIEW DEFINITION TO terminal02 --Permissions needed for executeUser GRANT SELECT to terminal02 GRANT SUBSCRIBE QUERY NOTIFICATIONS TO terminal02 GRANT RECEIVE ON QueryNotificationErrorsQueue TO terminal02 GRANT REFERENCES on CONTRACT::[http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification] to terminal02 EXEC sp_addrolemember 'sql_dependency_subscriber', 'terminal02' GRANT RECEIVE ON ChangeMessages TO terminal02; GRANT SEND ON SERVICE::ChangeNotifications TO terminal02; GRANT CREATE PROCEDURE to terminal02; GRANT CREATE QUEUE to terminal02; GRANT CREATE SERVICE to terminal02; GRANT SUBSCRIBE QUERY NOTIFICATIONS TO terminal02; GRANT INSERT ON SCHEMA::dbo TO terminal02; GRANT SELECT ON SCHEMA::dbo TO terminal02; GRANT ALTER ON SCHEMA::dbo TO terminal02; GRANT CONTROL ON SCHEMA::dbo TO terminal02; --GRANT CREATE SEQUENCE ON SCHEMA::dbo TO terminal02; GRANT DELETE ON SCHEMA::dbo TO terminal02; GRANT EXECUTE ON SCHEMA::dbo TO terminal02; GRANT INSERT ON SCHEMA::dbo TO terminal02; GRANT REFERENCES ON SCHEMA::dbo TO terminal02; GRANT SELECT ON SCHEMA::dbo TO terminal02; GRANT TAKE OWNERSHIP ON SCHEMA::dbo TO terminal02; GRANT UPDATE ON SCHEMA::dbo TO terminal02; GRANT VIEW CHANGE TRACKING ON SCHEMA::dbo TO terminal02; GRANT VIEW DEFINITION ON SCHEMA::dbo TO terminal02;
Zdeněk Neustupa