Existuje specifické chování třídy Microsoft SqlDependency. I když zavoláte metodu SqlDependency.Stop(), uvolněte SqlCommand a SqlConnection – stále v databázi zachová konverzační skupiny (sys.conversation_groups) a koncové body konverzace (sys.conversation_endpoints). Vypadá to, že SQL Server načte každý koncový bod konverzace a použije veškerou povolenou paměť. Zde testy, které to dokazují. Chcete-li tedy vyčistit všechny nepoužívané koncové body konverzace a uvolnit veškerou obsazenou paměť, musíte pro svou databázi spustit tento kód 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 vám také nedává příležitost přijímat VŠECHNY změny tabulky. Během opětovného předplatného SqlDependency tedy neobdržíte oznámení o změnách.
Abych se vyhnul všem těmto problémům, použil jsem další open source realizaci třídy SqlDependency - SqlDependencyEx . K přijímání událostí o změnách tabulky používá spouštěč databáze a nativní upozornění Service Broker. Toto je příklad použití:
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);
Doufám, že to pomůže.