很长一段时间后SqlDependency错误
我有一个Windows服务使用SqlDependency类监听表中的插入。
它工作好几天但后来突然停止工作。
在正常情况下,我收到更改事件
e.Type = SqlNotificationType。 更改
e.Info = SqlNotificationInfo。 插入
e.Source = SqlNotificationSource。 数据
如果没有任何变化,我每隔3600秒就会收到超时事件
e.Type = SqlNotificationType。 更改
e.Info = SqlNotificationInfo。 错误
e.Source = SqlNotificationSource。 超时
或(不知道为什么有两个不同的超时事件)
e.Type = SqlNotificationType。 更改
e.Info = SqlNotificationInfo。 未知
e.Source = SqlNotificationSource。 超时
这可以工作一周或更长时间但突然间我不再接收更改事件,而是每隔60秒接收一次事件
e.Type = SqlNotificationType。 更改
e.Info = SqlNotificationInfo。 错误
e.Source = SqlNotificationSource。 客户
SqlNotificationSource.Client的msdn文档说
发生客户端启动的通知,例如客户端超时或尝试将命令添加到已触发的依赖项。
我认为这意味着在创建依赖项时发生了一个时间。
相同的代码一直在运行,如下所示:
private void CreateDependency() { using (var connection = new SqlConnection(_connectionString)) { connection.Open(); var command = new SqlCommand(); command.CommandText = "SELECT ..."; command.Connection = connection; new SqlDependency(command, "ServiceName", DependencyTimeout).OnChange += OnChange; command.ExecuteNonQuery(); } } private void OnChange(object sender, SqlNotificationEventArgs e) { ((SqlDependency)sender).OnChange -= OnChange; if (e.Type == SqlNotificationType.Change && e.Info == SqlNotificationInfo.Insert) { _changeWorkerNotifier.Set(); // AutoResetEvent } CreateDependency(); }
如果我重新启动我的服务它再次正常工作。
我做了一些调查,发现错误似乎是在服务器上的计划备份之后开始的(每天都会发生)。 得到另一个应用程序,我大约在同一时间得到错误
从服务器接收结果时发生传输级错误。 (提供者:TCP提供者,错误:0 – 信号量超时期限已过期。)
我最初的猜测是, SqlDependency.Start()
创建了与服务器的连接,该连接在计划备份期间出现故障并且永远不会恢复。 但msdn文档中的第一行说
当SQL Server连接中发生错误时,SqlDependency侦听器将重新启动。
关于如何解决这个问题的任何想法?
(我当然可以让服务失败并让服务管理器重新启动它。问题是该服务还做其他事情需要正常关闭所以我不能只做Enviroment.Exit(-1)事件处理程序
找到原因和解决方案。
首先,我发现了这条线
当SQL Server连接中发生错误时,SqlDependency侦听器将重新启动。
仅出现在.Net 4文档中。
一些测试表明,这不仅仅是文档的变化! 使用CLR4运行时不会出现客户端/错误事件。
因此原因是连接错误,它在.Net 4中的SqlDependency内处理,但在早期版本中没有。
在.Net 2-3.5中,可以使用SqlDependency.Stop()
/ SqlDependency.Start()
在错误之后恢复。
不太喜欢Stop / Start解决方案,因为如果连接错误无法恢复,我需要逻辑来打破循环。 我决定在出现错误时停止服务,让服务管理器重新启动它。 (这使问题在事件日志等中可见)
我的处理程序现在如下所示:
private void OnChange(object sender, SqlNotificationEventArgs e) { ((SqlDependency)sender).OnChange -= OnChange; if (e.Source == SqlNotificationSource.Timeout) { // just restart notification } else if (e.Source != SqlNotificationSource.Data) { Logger.Error("Unhandled change notification {0}/{1} ({2})", e.Type, e.Info, e.Source); ServiceRunner.ShutDown(true); } else if (e.Type == SqlNotificationType.Change && e.Info == SqlNotificationInfo.Insert) { _changeWorkerNotifier.Set(); // AutoResetEvent } else { Logger.Log("Ignored change notification {0}/{1} ({2})", e.Type, e.Info, e.Source); } CreateDependency(); }
**编辑**
这是我在启动时调用的代码
上述就是C#学习教程:很长一段时间后SqlDependency错误分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
private void ClearOldSubscriptions() { using (var connection = new SqlConnection(_connectionString)) using (var command = new SqlCommand()) { string sql = ////@"DECLARE @UniqueTimeout AS int = 3586; " + @"DECLARE @SubscriptionId AS int; " + @"DECLARE @Sql AS varchar(max); " + @"DECLARE SubscriptionCursor CURSOR LOCAL FAST_FORWARD " + @" FOR " + @" SELECT id " + @" FROM sys.dm_qn_subscriptions " + @" WHERE database_id = DB_ID() " + @" AND timeout = @UniqueTimeout " + @"OPEN SubscriptionCursor; " + @"FETCH NEXT FROM SubscriptionCursor INTO @SubscriptionId; " + @"WHILE @@FETCH_STATUS = 0 " + @"BEGIN " + @" SET @Sql = 'KILL QUERY NOTIFICATION SUBSCRIPTION ' + CONVERT(varchar, @SubscriptionId); " + @" EXEC(@Sql); " + @" " + @" FETCH NEXT FROM SubscriptionCursor INTO @SubscriptionId; " + @"END"; command.Connection = connection; command.CommandType = CommandType.Text; command.CommandText = sql; command.Parameters.Add("@UniqueTimeout", SqlDbType.Int).Value = DependencyTimeout; connection.Open(); command.ExecuteNonQuery(); } } private void ClearNotificationQueue() { using (var connection = new SqlConnection(_connectionString)) using (var command = new SqlCommand()) { string sql = @"DECLARE @Conversation AS uniqueidentifier; " + @"DECLARE ConversationCursor CURSOR LOCAL FAST_FORWARD " + @" FOR " + @" SELECT conversation_handle " + @" FROM {@Queue} " + @" " + @"OPEN ConversationCursor; " + @"FETCH NEXT FROM ConversationCursor INTO @Conversation; " + @"WHILE @@FETCH_STATUS = 0 " + @"BEGIN " + @" END CONVERSATION @Conversation WITH CLEANUP; " + @" " + @" FETCH NEXT FROM ConversationCursor INTO @Conversation; " + @"END " + @""; sql = sql.Replace("{@Queue}", NotificationQueue); command.Connection = connection; command.CommandType = CommandType.Text; command.CommandText = sql; connection.Open(); command.ExecuteNonQuery(); } }
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/950615.html