如何从SQL Server内存中清理SqlDependency?

如何清理SQL Server以摆脱过期的SqlDependency对象? 在从SqlDepedency对象接收到事件后,我需要创build一个新的事件,然后才能获取新事件。 但是,SQL Server进程的内存使用会一直攀升,直到超出允许的内存(SQL Server Express)。 我如何摆脱旧的查询?

码:

 // Func: RegisterTableListener using (SqlConnection cn = new SqlConnection(Properties.Settings.Default.DatabseEventConnectionString)) { if (cmd == null) { cmd = cn.CreateCommand(); cmd.CommandType = CommandType.Text; cmd.CommandText = "SELECT HostName, LastStatus, LastDetails, xml FROM dbo.[SystemTable]"; } lock (cmd) { cmd.Connection = cn; cn.Open(); cmd.Notification = null; // creates a new dependency for the SqlCommand if (dep == null) dep = new SqlDependency(cmd); // creates an event handler for the notification of data // changes in the database. dep.OnChange += new OnChangeEventHandler(dependency_OnChange); using (SqlDataReader reader = cmd.ExecuteReader()) { // code here to read } } } // Func dependency_OnChange //SqlDependency dep = sender as SqlDependency; dep.OnChange -= dependency_OnChange; RegisterTableListener(); 

有一个Microsoft SqlDependency类的特定行为。 即使您调用SqlDependency.Stop()方法,也要释放SqlCommand和SqlConnection – 它仍然保留数据库中的对话组(sys.conversation_groups)和对话端点(sys.conversation_endpoints)。 它看起来像SQL Server加载每个对话端点并使用所有允许的内存。 这里的testingcertificate了这一点。 所以,要清除所有未使用的对话端点并释放所有占用的内存,您必须为您的数据库启动此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类的另一个开源实现 – SqlDependencyEx 。 它使用数据库触发器和本机Service Broker通知来接收有关表的更改的事件。 这是一个用法示例:

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

希望这可以帮助。

我面对完全相同的问题。 我正在创build一个caching来自SQL Server 2005数据库的一些查询的数据访问组件。 caching使用这个shiny的新的,以及不再是新的SqlDependency方法无效。

因为这个组件将在ASP.NET以及Forms和Windows Service应用程序中使用,所以我正在寻找一种通用的方式来(在内部)调用SqlDependency.Stop()。

使用终结者也是我的第一个想法,而这一切都没有成功。 我第二次尝试是使用AppDomain.DomainUnload事件处理程序。

毕竟,这似乎工作…但VS 2005中的内置Web服务器将执行SqlDependy.Stop()100%CPU挂起4-5分钟。 事实上,我不记得任何其他进程阻止我的机器(Pentium M笔记本电脑)可重现如此糟糕,我几乎无法提出任务pipe理器…我没想到这是可能的用户空间,甚至托pipe代码(SQL Server正在另一个盒子上运行)。在这期间,即使性能监视器也拒绝logging任何东西,所以我不能说是否有很多Windows句柄或者.NETexception被包含或者其他什么东西…

从Application_End事件调用它工作正常(只需要几毫秒),但是这是特定于ASP.NET。

有任何想法吗