C# 如何从SQLServer内存中清除SqlDependency?

C# 如何从SQLServer内存中清除SqlDependency?,c#,sql,sql-server-2008,sqldependency,C#,Sql,Sql Server 2008,Sqldependency,如何清理SQL Server以除去过期的SqlDependency对象?从sqldepency对象接收事件后,我需要创建一个新的事件,然后才能获取新事件。但是,SQL Server进程的内存使用会逐渐增加,直到耗尽允许的内存(SQL Server Express)。如何摆脱旧的查询 代码: Microsoft SqlDependency类有一个特定的行为。即使调用SqlDependency.Stop()方法,释放SqlCommand和SqlConnection—它仍然在数据库中保留会话组(sys

如何清理SQL Server以除去过期的
SqlDependency
对象?从
sqldepency
对象接收事件后,我需要创建一个新的事件,然后才能获取新事件。但是,SQL Server进程的内存使用会逐渐增加,直到耗尽允许的内存(SQL Server Express)。如何摆脱旧的查询

代码:


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类的另一个开源实现-。它使用数据库触发器和本机ServiceBroker通知来接收有关表更改的事件。这是一个使用示例:

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

希望这有帮助。

您如何创建
SqlDependency
对象?请张贴您的密码。你处理得好吗?我明天上班时会用代码更新我的评论。Sudo:SqlDependency-dep=newsqldependency(cmd);dep.OnChange+=乐趣;SqlDependency未实现IDisposableI已用代码更新。即使我只运行一个SqlDepdency实例,每次调用Stop和Start,内存也会增加。我不知道发生了什么。如果CEP.state='DI'或CEP.state='CD',这一行是什么意思。你想做什么。请帮助我理解。thanks@Mou
DI
表示“断开连接绑定”
CD
表示“关闭”。带有此标记的对话终结点没有由
SqlDependency
设置的生存期。这意味着它们将在数据库中,直到您强制清理它们。根据文章(最后)的说法,这是清理旧对话端点的正确方法。这是否意味着如果我使用这个sql
,其中CEP.state='DI'或CEP.state='CD'
,那么旧对话将被删除?@Mou这是另一个内存泄漏的证据和inventor对它的评论。最后你可以找到一个类似的解决方案。下面是一些单元测试,它们表明
SqlDependency
在数据库中保持未关闭或终生不存在的会话端点@我上面提到的Rusanu的文章给出了一个仅使用
CD
状态清理旧会话端点的示例。但根据我的经验,
DI
端点也一直存在于数据库中。
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);