void dependency_OnChange(object sender, SqlNotificationEventArgs e)
It is expected that you check SqlNotificationEventArgs and find out why you received a notification, data change, or something else. Check Info as Insert / Update / Delete , Check Source as Data . Check Type as Change .
Most likely, your request immediately signals that it does not comply with the restrictions imposed on notification of requests . Yes, I know that the link points to indexed views, and if you want to understand why, read The Mysterious Notification .
You also have a race condition between your update pending _ResetEvent and the _ResetEvent callback. T1 causes an update. Meanwhile, an unrelated update occurs in the data, and callbacks are called. The _ResetEvent parameter is set. T1 completes the update and waits for _ResteEvent, which is signaled, so it continues. The caller assumes that a callback for his own update has occurred and the cache has been updated, but this is not true.
The second serious problem is that the code is incorrect in the presence of transactions. UpdateXXX assumes that a callback for its own update will occur immediately and wait for it. The request notification will be sent by the engine only after the update has been fixed, therefore, when TransactionScope is present, the UpdateXXX method will block waiting for the notification, which cannot appear until UpdateXXX returns (live deadlock).
It is also unclear what the purpose of TrackForChanges is. You read SqlDataReader (sqlCommand.ExecuteReader), but ignore the result. With a notification of requests, you send a request, read the result of itse , and you will be notified when this result has changed.
And finally, it never reads the data in the SqlDependency notification callback .