方案
粗略的代码大纲
使用this blog post作为模板,代码大致遵循此模式
配置依赖关系定位特定服务(请参阅下面的代码)
private async void ConfigureDependencyUsingStoreProcedureAndSpecificQueue()
{
if (null != this.sampleSqlDependency)
{
this.sampleSqlDependency.OnChange -= null;
}
if (null != this.sampleSqlCommand)
{
this.sampleSqlCommand.Dispose();
}
if (null != this.sampleSqlConnection)
{
this.sampleSqlConnection.Dispose();
}
this.sampleSqlDependency = null;
this.sampleSqlCommand = null;
this.sampleSqlConnection = null;
//// Create connection.
this.sampleSqlConnection = new SqlConnection(this.dbConnectionString);
//// Create command.
this.sampleSqlCommand = new SqlCommand { Connection = this.sampleSqlConnection };
this.sampleSqlCommand.CommandType = CommandType.StoredProcedure;
this.sampleSqlCommand.CommandText = this.notificationStoredProcedure;
this.sampleSqlCommand.Notification = null;
//// Create Sql Dependency.
this.sampleSqlDependency = new SqlDependency(this.sampleSqlCommand, "service=" + this.notificationServiceName +"; Local database=" + this.databaseName, this.notificationTimeout);
this.sampleSqlDependency.OnChange += this.SqlDependencyOnChange;
await this.sampleSqlCommand.Connection.OpenAsync();
await this.sampleSqlCommand.ExecuteReaderAsync(CommandBehavior.CloseConnection);
if (null != this.sampleSqlCommand)
{
this.sampleSqlCommand.Dispose();
}
if (null != this.sampleSqlConnection)
{
this.sampleSqlConnection.Dispose();
}
处理SqlDependencyOnChange事件,如下所示。再次调用ConfigureDependency代码
private void SqlDependencyOnChange(object sender, SqlNotificationEventArgs eventArgs)
{
if (eventArgs.Info == SqlNotificationInfo.Invalid)
{
Console.WriteLine("The above notification query is not valid.");
}
else
{
Console.WriteLine("\nNotification Time: {0}", DateTime.Now);
Console.WriteLine("\nNotification Info: " + eventArgs.Info);
Console.WriteLine("Notification source: " + eventArgs.Source);
Console.WriteLine("Notification type: " + eventArgs.Type + "\n");
}
switch (optionSelected)
{
case "1":
this.ConfigureDependencyUsingStoreProcedureAndDefaultQueue();
break;
case "2":
this.ConfigureDependencyUsingStoreProcedureAndSpecificQueue();
break;
case "3":
this.ConfigureDependencyUsingTextQueryAndDefaultQueue();
break;
case "4":
this.ConfigureDependencyUsingTextQueryAndSpecificQueue();
break;
}
}
在app关闭时调用SqlDependency.Stop(this.dbConnectionString,this.notificationQueueName);.这返回true,根据documentation表示监听器已完全停止。
问题面对
我接着看到,当订阅达到超时时间时,它会触发并将消息丢弃到等待消耗的依赖队列中。
如果这些消息留在队列中,则在下次启动时,应用程序将抛出字典中不存在给定的密钥。
此外,如果我调用SQLDependency.Stop()并让应用程序继续运行,它仍会消耗QN引发的超时时间。
我在这里失去了什么步骤,因为如果消息在静态队列中被删除导致字典异常中没有给定的密钥,我可能会遇到问题。
由于
答案 0 :(得分:0)
返回true,根据文档表示监听器已完全停止。
对于 server 状态和队列状态没有任何承诺。这些将比您的易失性应用程序状态更长,并且在下次启动时,您将从应用程序脱机/关闭时查找通知。您必须相应地编码,并期望这样的期望(例如,忽略字典中没有的键)。
请注意,即使SqlDependency.Stop()
会尝试停止待处理的订阅通知,也无法保证成功,因为可能会有正在传输的通知(即通过Service Broker暂挂,通知可能在sys.trasnmission_queue
)。等待所有传输通知以消除交付也是不可行的。
此外,您的应用程序不会像现在一样处理备份还原方案。还原的备份可能包含待处理的通知请求,这些请求将在还原时失效并触发通知消息。当应用程序连接时,它会找到那些意外的通知。
最终应用程序将无法处理自己的断开连接/崩溃。如果您依靠SqlDependency.Stop()
成功,然后下次成功成功,如果您无法拨打SqlDependency.Stop()
(=>任何非优雅停靠点),您将无法启动
由于所有这些原因,您必须能够处理不在字典中的密钥。