Существует определенное поведение класса Microsoft SqlDependency. Несмотря на то, что вы вызываете метод SqlDependency.Stop (), освобождаете SqlCommand и SqlConnection - он по-прежнему сохраняет группы беседы (sys.conversation_groups) и конечные точки беседы (sys.conversation_endpoints) в базе данных. Похоже, что SQL Server загружает каждую конечную точку диалога и использует всю разрешенную память. Здесь тесты, которые доказывают это. Итак, чтобы очистить все неиспользуемые конечные точки диалога и освободить всю занятую память, вам нужно запустить этот код SQL для вашей базы данных:
DECLARE @ConvHandle uniqueidentifier
DECLARE Conv CURSOR FOR
SELECT CEP.conversation_handle FROM sys.conversation_endpoints CEP
WHERE CEP.state = 'DI' or CEP.state = 'CD'
OPEN Conv;
FETCH NEXT FROM Conv INTO @ConvHandle;
WHILE (@@FETCH_STATUS = 0) BEGIN
END CONVERSATION @ConvHandle WITH CLEANUP;
FETCH NEXT FROM Conv INTO @ConvHandle;
END
CLOSE Conv;
DEALLOCATE Conv;
Кроме того, SqlDependency не дает вам возможности получать ВСЕ изменения таблицы. Таким образом, вы не получите уведомление об изменениях во время повторной подписки SqlDependency.
Чтобы избежать всех этих проблем, я использовал другую реализацию класса SqlDependency с открытым исходным кодом - SqlDependencyEx . Он использует триггер базы данных и собственное уведомление Service Broker для получения событий об изменениях таблицы. Это пример использования:
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);
Надеюсь, это поможет.