Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Comment nettoyer SqlDependency de la mémoire SQL Server ?

Il existe un comportement spécifique de la classe Microsoft SqlDependency. Même si vous appelez la méthode SqlDependency.Stop(), relâchez SqlCommand et SqlConnection - il conserve toujours les groupes de conversation (sys.conversation_groups) et les points de terminaison de conversation (sys.conversation_endpoints) dans la base de données. Il semble que SQL Server charge chaque point de terminaison de conversation et utilise toute la mémoire autorisée. ici tests qui le prouvent. Ainsi, pour nettoyer tous les points de terminaison de conversation inutilisés et libérer toute la mémoire occupée, vous devez démarrer ce code SQL pour votre base de données :

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;

De plus, SqlDependency ne vous donne pas la possibilité de recevoir TOUTES les modifications de la table. Ainsi, vous ne recevez pas de notification concernant les modifications lors de la réinscription de SqlDependency.

Pour éviter tous ces problèmes, j'avais utilisé une autre réalisation open source de la classe SqlDependency - SqlDependencyEx . Il utilise un déclencheur de base de données et une notification native de Service Broker pour recevoir des événements sur les modifications de la table. Voici un exemple d'utilisation :

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);

J'espère que cela vous aidera.