C# 调用SqlDependency.Start连续两次,第二次失败?
多次调用C# 调用SqlDependency.Start连续两次,第二次失败?,c#,sql-server,service-broker,sqldependency,sqlcachedependency,C#,Sql Server,Service Broker,Sqldependency,Sqlcachedependency,多次调用SqlDependency.Start的目的是确保在执行其他操作(例如基于命令创建SqlCacheDependency的新实例)之前一切正常。根据Microsoft关于SqlDependency.Start的文档,在这里(备注部分),似乎多次调用SqlDependency.Start完全可以: 具有相同参数(调用线程中的相同连接字符串和Windows凭据)的多个调用有效 但实际上,第二次调用它可能会失败(对我来说,它从来没有成功过),使所有下一次调用SqlDependency.Start
SqlDependency.Start
的目的是确保在执行其他操作(例如基于命令创建SqlCacheDependency
的新实例)之前一切正常。根据Microsoft关于SqlDependency.Start
的文档,在这里(备注部分),似乎多次调用SqlDependency.Start
完全可以:
具有相同参数(调用线程中的相同连接字符串和Windows凭据)的多个调用有效
但实际上,第二次调用它可能会失败(对我来说,它从来没有成功过),使所有下一次调用SqlDependency.Start的尝试都失败(通过返回false
,不会引发异常)
我所做的应该满足第一个限制(在上面链接的备注部分中提到),即对SqlDependency.Start
的所有调用都具有相同的参数(实际上只有一个相同的参数,即连接字符串)。它看起来就像这样:
//at initialization step (such as in `Application_Start()` in ASP.NET MVC)
SqlDependency.Start(myConnectionString);//this usually returns OK
//later at the time before creating an instance of SqlCacheDependency
//I tried to call the Start method again to ensure everything is ok
var ok = SqlDependency.Start(myConnectionString);//almost always false
if(ok){
//almost never reach here ...
}
所以很难理解微软所说的(在备注部分的第一个限制中),这两个电话是完全相同的。但在第二次调用失败的情况下,之后使用的任何相同调用仍将失败(这意味着,一旦我尝试多次调用它,就没有机会成功启动它)
当我在Sql Server中看到日志时,我可以看到有很多消息说找不到远程服务。。。因为它不存在
我不需要解决或解决这个问题,我只需要解释一下为什么它不能像微软所说的那样正常工作,或者我误解了微软所说的?正如州政府的评论和文档中提到的:
返回
true
如果侦听器初始化成功<如果已存在兼容的侦听器,则代码>false
正如文档中的注释所述,SqlDependency.Start()
和SqlDependency.Stop()
将跟踪每个调用的数量。如果对SqlDependency.Start()
的调用次数超过了对SqlDependency.Stop()
的调用次数,它将确保后台连接正在运行或正在设置(尽管我认为如果调用SqlDependency.Stop()
的次数超过调用SqlDependency.Start()的次数,它会失去跟踪并重置计数)
)
Start()
错误
这可能有助于澄清SqlDependency.Start()
可能失败。使其失败的一种方法是使用不同的连接字符串从一个AppDomain
多次调用它。在特定的AppDomain
中,如果传入不同的连接字符串,SqlDependency.Start()
将引发异常,除非连接字符串中至少有一个以下属性与以前传递的连接字符串不同:
数据库名称
用户名
也就是说,您需要规范化或缓存第一次传递给SqlDependency.Start()
的连接字符串,以便您永远不会传递一个字符串,例如,Max Pool Size
的值不同。我认为这样做是为了避免为单个进程创建大量代理队列和连接。此外,当您稍后实际设置SqlDependency
时,当它尝试将命令与代理队列相匹配时,它可能会使用这些不同的连接字符串属性来决定使用哪个队列
ASP.NET生命周期
从“生命周期事件和Global.asax文件”下的文档中,请注意以下内容:
Application\u Start
方法是一种实例方法,仅在应用程序启动时调用,这通常发生在应用程序的第一个HTTP请求期间。文件特别指出:
在应用程序启动期间,应仅设置静态数据。不要设置任何实例数据,因为它将仅对创建的类的第一个实例可用
清理在Application\u Start
中初始化的内容时应使用的方法是Application\u End
。当webapp正常停止时,将创建应用程序类的实例,并对其调用application\u End
。请注意,这可能是与调用的application\u Start
不同的应用程序类实例
由于ASP.NET的体系结构,每个正在处理的请求都需要一个不同的HttpApplication
类实例。这意味着将创建多个实例来处理并发请求。文档还指出,出于性能原因,应用程序类实例可能会被框架缓存并用于多个请求。为了让您有机会在实例级别初始化和清理应用程序类,您可以实现Init
和Dispose
方法。这些方法应该配置不特定于特定请求的应用程序类实例变量。文件规定:
在创建所有模块后,为HttpApplication
类的每个实例调用一次
在销毁应用程序实例之前调用
但是,您提到您正在Application\u Start
中初始化全局状态(即SqlDependency.Start()
),并在Dispose()
中清理全局状态(即SqlDependency.Stop()
)。由于Application\u Start
将被调用一次,用于配置statics/globals和Dispose()