Há um comportamento específico da classe Microsoft SqlDependency. Mesmo que você chame o método SqlDependency.Stop(), libere SqlCommand e SqlConnection - ele ainda mantém grupos de conversação (sys.conversation_groups) e terminais de conversação (sys.conversation_endpoints) no banco de dados. Parece que o SQL Server carrega todos os endpoints de conversa e usa toda a memória permitida. Aqui testes que comprovam isso. Portanto, para limpar todos os endpoints de conversação não utilizados e liberar toda a memória ocupada, você deve iniciar este código SQL para seu banco de dados:
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;
Além disso, SqlDependency não lhe dá a oportunidade de receber TODAS as alterações da tabela. Portanto, você não recebe notificação sobre alterações durante a nova assinatura do SqlDependency.
Para evitar todos esses problemas, usei outra realização de código aberto da classe SqlDependency - SqlDependencyEx . Ele usa o gatilho do banco de dados e a notificação nativa do Service Broker para receber eventos sobre as alterações da tabela. Este é um exemplo de uso:
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);
Espero que isto ajude.