sql >> Base de Datos >  >> RDS >> Sqlserver

¿Cómo limpio SqlDependency de la memoria de SQL Server?

Hay un comportamiento específico de la clase Microsoft SqlDependency. Aunque llame al método SqlDependency.Stop(), libere SqlCommand y SqlConnection; aún mantiene los grupos de conversación (sys.conversation_groups) y los puntos finales de conversación (sys.conversation_endpoints) en la base de datos. Parece que SQL Server carga todos los puntos finales de conversación y usa toda la memoria permitida. Aquí pruebas que lo demuestren. Entonces, para limpiar todos los puntos finales de conversación no utilizados y liberar toda la memoria ocupada, debe iniciar este código SQL para su base de datos:

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;

Además, SqlDependency no le brinda la oportunidad de recibir TODOS los cambios de la tabla. Por lo tanto, no recibe notificaciones sobre cambios durante la nueva suscripción de SqlDependency.

Para evitar todos estos problemas, utilicé otra realización de código abierto de la clase SqlDependency:SqlDependencyEx . Utiliza el activador de la base de datos y la notificación nativa de Service Broker para recibir eventos sobre cambios en la tabla. Este es un ejemplo 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 esto ayude.