Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# SQL查询通知在scaleout设置(SQL Server)中并不总是有效_C#_Sql Server_Notifications_Signalr_Sqldependency - Fatal编程技术网

C# SQL查询通知在scaleout设置(SQL Server)中并不总是有效

C# SQL查询通知在scaleout设置(SQL Server)中并不总是有效,c#,sql-server,notifications,signalr,sqldependency,C#,Sql Server,Notifications,Signalr,Sqldependency,SQL查询通知在我们的环境中并不总是有效的。它们似乎工作了一段时间,然后我们在SqlDependency.Start(…)方法调用上得到ArgumentException(模拟的无效令牌-它不能复制)异常,SqlMessageBus返回到使用轮询机制。在此之后,在SQL消息总线被释放之前,不会尝试SQL查询通知 似乎SqlMessageBus并不总是看到SqlDependency已经启动,并尝试再次启动它 在日志(见下文)中,我看到了以下事件序列: 启动SQL通知侦听器 SQL通知侦听器已启动

SQL查询通知在我们的环境中并不总是有效的。它们似乎工作了一段时间,然后我们在SqlDependency.Start(…)方法调用上得到ArgumentException(模拟的无效令牌-它不能复制)异常,SqlMessageBus返回到使用轮询机制。在此之后,在SQL消息总线被释放之前,不会尝试SQL查询通知

似乎SqlMessageBus并不总是看到SqlDependency已经启动,并尝试再次启动它

在日志(见下文)中,我看到了以下事件序列:

  • 启动SQL通知侦听器
  • SQL通知侦听器已启动
  • 触发SQL通知更改
  • 启动SQL通知侦听器
  • SQL通知侦听器已在运行
  • 设置SQL通知
  • 触发SQL通知更改
  • SQL通知超时
  • 再次启动接收循环以处理更新
  • 启动SQL通知侦听器
  • 启动SQL通知侦听器时出错
环境:

  • .NET 4.5.2
  • Windows 7上的WinForms客户端
  • 在Windows Server 2012 R2上的IIS 8.5中托管2台应用程序服务器(使用Windows身份验证和模拟)
  • 负载平衡器
  • 信号机2.2
  • SQL Server 2008 R2 SP3(使用SQL Server身份验证)
以下是捕获日志的摘录。如果需要,我可以提供完整的日志

...
SignalR.SqlMessageBus Verbose: 0 : Stream 0 : Starting SQL notification listener
    DateTime=2015-02-06T18:47:37.3054459Z
SignalR.SqlMessageBus Verbose: 0 : Stream 0 : SQL notification listener started
    DateTime=2015-02-06T18:47:37.3679593Z
...
SignalR.SqlMessageBus Verbose: 0 : Stream 0 : SqlReceiver last payload ID=0, new payload ID=1
    DateTime=2015-02-06T18:47:38.1805287Z
SignalR.SqlMessageBus Verbose: 0 : Stream 0 : Updated receive reader initial payload ID parameter=1
    DateTime=2015-02-06T18:47:38.1805287Z
SignalR.SqlMessageBus Verbose: 0 : Stream 0 : Payload 1 containing 1 message(s) received
    DateTime=2015-02-06T18:47:38.1805287Z
SignalR.ScaleoutMessageBus Information: 0 : OnReceived(0, 1, 1)
    DateTime=2015-02-06T18:47:38.1805287Z
SignalR.SqlMessageBus Verbose: 0 : Stream 0 : 1 records received
    DateTime=2015-02-06T18:47:38.1961135Z
...
SignalR.SqlMessageBus Verbose: 0 : Stream 0 : No records received while setting up SQL notification
    DateTime=2015-02-06T18:47:47.1184053Z
SignalR.SqlMessageBus Verbose: 0 : Stream 0 : Receive loop exiting
    DateTime=2015-02-06T18:47:47.1184053Z
SignalR.SqlMessageBus Information: 0 : Stream 0 : SqlReceiver.Receive returned
    DateTime=2015-02-06T18:47:47.1184053Z
SignalR.SqlMessageBus Information: 0 : Stream 0 : SQL notification change fired
    DateTime=2015-02-06T18:48:13.1196355Z
SignalR.SqlMessageBus Verbose: 0 : Stream 0 : SQL notification details: Type=Change, Source=Data, Info=Update
    DateTime=2015-02-06T18:48:13.1196355Z
SignalR.SqlMessageBus Information: 0 : Stream 0 : Starting receive loop again to process updates
    DateTime=2015-02-06T18:48:13.1196355Z
SignalR.SqlMessageBus Verbose: 0 : Stream 0 : Starting SQL notification listener
    DateTime=2015-02-06T18:48:13.1196355Z
SignalR.SqlMessageBus Verbose: 0 : Stream 0 : SQL notification listener was already running
    DateTime=2015-02-06T18:48:13.1196355Z
SignalR.SqlMessageBus Verbose: 0 : Created DbCommand: CommandType=Text, CommandText=SELECT [PayloadId], [Payload], [InsertedOn] FROM [SignalR].[Messages_0] WHERE [PayloadId] > @PayloadId, Parameters= [Name=PayloadId, Value=1]
    DateTime=2015-02-06T18:48:13.1196355Z
SignalR.SqlMessageBus Verbose: 0 : Stream 0 : SqlReceiver last payload ID=1, new payload ID=2
    DateTime=2015-02-06T18:48:13.1196355Z
SignalR.SqlMessageBus Verbose: 0 : Stream 0 : Updated receive reader initial payload ID parameter=2
    DateTime=2015-02-06T18:48:13.1196355Z
SignalR.SqlMessageBus Verbose: 0 : Stream 0 : Payload 2 containing 1 message(s) received
    DateTime=2015-02-06T18:48:13.1196355Z
SignalR.ScaleoutMessageBus Information: 0 : OnReceived(0, 2, 1)
    DateTime=2015-02-06T18:48:13.1196355Z
SignalR.SqlMessageBus Verbose: 0 : Stream 0 : 1 records received
    DateTime=2015-02-06T18:48:13.1196355Z
...
SignalR.SqlMessageBus Verbose: 0 : Stream 0 : Setting up SQL notification
    DateTime=2015-02-06T18:48:27.8859474Z
SignalR.SqlMessageBus Verbose: 0 : Created DbCommand: CommandType=Text, CommandText=SELECT [PayloadId], [Payload], [InsertedOn] FROM [SignalR].[Messages_0] WHERE [PayloadId] > @PayloadId, Parameters= [Name=PayloadId, Value=3]
    DateTime=2015-02-06T18:48:27.8859474Z
SignalR.SqlMessageBus Verbose: 0 : Stream 0 : No records received while setting up SQL notification
    DateTime=2015-02-06T18:48:27.8859474Z
SignalR.SqlMessageBus Verbose: 0 : Stream 0 : Receive loop exiting
    DateTime=2015-02-06T18:48:27.8859474Z
SignalR.SqlMessageBus Information: 0 : Stream 0 : SQL notification change fired
    DateTime=2015-02-06T18:49:27.9200020Z
SignalR.SqlMessageBus Verbose: 0 : Stream 0 : SQL notification timed out
    DateTime=2015-02-06T18:49:27.9200020Z
SignalR.SqlMessageBus Information: 0 : Stream 0 : Starting receive loop again to process updates
    DateTime=2015-02-06T18:49:27.9200020Z
SignalR.SqlMessageBus Verbose: 0 : Stream 0 : Starting SQL notification listener
    DateTime=2015-02-06T18:49:27.9200020Z
SignalR.SqlMessageBus Verbose: 0 : Stream 0 : SQL notification listener was already running
    DateTime=2015-02-06T18:49:27.9200020Z
...
SignalR.SqlMessageBus Verbose: 0 : Stream 0 : Setting up SQL notification
    DateTime=2015-02-06T18:50:51.8614352Z
SignalR.SqlMessageBus Verbose: 0 : Created DbCommand: CommandType=Text, CommandText=SELECT [PayloadId], [Payload], [InsertedOn] FROM [SignalR].[Messages_0] WHERE [PayloadId] > @PayloadId, Parameters= [Name=PayloadId, Value=3]
    DateTime=2015-02-06T18:50:51.8614352Z
SignalR.SqlMessageBus Verbose: 0 : Stream 0 : No records received while setting up SQL notification
    DateTime=2015-02-06T18:50:51.8614352Z
SignalR.SqlMessageBus Verbose: 0 : Stream 0 : Receive loop exiting
    DateTime=2015-02-06T18:50:51.8614352Z
SignalR.SqlMessageBus Information: 0 : Stream 0 : SQL notification change fired
    DateTime=2015-02-06T18:51:58.0520336Z
SignalR.SqlMessageBus Verbose: 0 : Stream 0 : SQL notification timed out
    DateTime=2015-02-06T18:51:58.0520336Z
SignalR.SqlMessageBus Information: 0 : Stream 0 : Starting receive loop again to process updates
    DateTime=2015-02-06T18:51:58.0520336Z
SignalR.SqlMessageBus Verbose: 0 : Stream 0 : Starting SQL notification listener
    DateTime=2015-02-06T18:51:58.0520336Z
SignalR.SqlMessageBus Error: 0 : Stream 0 : Error starting SQL notification listener: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ArgumentException: Invalid token for impersonation - it cannot be duplicated.
   at System.Security.Principal.WindowsIdentity.CreateFromToken(IntPtr userToken)
   at System.Security.Principal.WindowsIdentity..ctor(SerializationInfo info)
   --- End of inner exception stack trace ---

Server stack trace: 
   at System.RuntimeMethodHandle.SerializationInvoke(IRuntimeMethodInfo method, Object target, SerializationInfo info, StreamingContext& context)
   at System.Runtime.Serialization.ObjectManager.CompleteISerializableObject(Object obj, SerializationInfo info, StreamingContext context)
   at System.Runtime.Serialization.ObjectManager.FixupSpecialObject(ObjectHolder holder)
   at System.Runtime.Serialization.ObjectManager.DoFixups()
   at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
   at System.Runtime.Remoting.Channels.CrossAppDomainSerializer.DeserializeObject(MemoryStream stm)
   at System.Runtime.Remoting.Messaging.SmuggledMethodCallMessage.FixupForNewAppDomain()
   at System.Runtime.Remoting.Channels.CrossAppDomainSink.DoDispatch(Byte[] reqStmBuff, SmuggledMethodCallMessage smuggledMcm, SmuggledMethodReturnMessage& smuggledMrm)
   at System.Runtime.Remoting.Channels.CrossAppDomainSink.DoTransitionDispatchCallback(Object[] args)

Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at SqlDependencyProcessDispatcher.StartWithDefault(String connectionString, String& server, DbConnectionPoolIdentity& identity, String& user, String& database, String& service, String appDomainKey, SqlDependencyPerAppDomainDispatcher dispatcher, Boolean& errorOccurred, Boolean& appDomainStart)
   at System.Data.SqlClient.SqlDependency.Start(String connectionString, String queue, Boolean useDefaults)
   at Microsoft.AspNet.SignalR.SqlServer.ObservableDbOperation.StartSqlDependencyListener()
    DateTime=2015-02-06T18:51:58.0520336Z
...
有人见过这个问题吗

当当前线程中的
HttpContext.Current.User.Identity
为空时,通常会引发异常“用于模拟的无效令牌-无法复制”,可能您应该在SqlDependency.Start()方法之前/之后检查它


Current不会自然地在TPL(异步/等待方法)隐式创建的线程上传播,也许您应该看看这方面。如果您的服务器端应用程序是asp.net,请尝试在您的应用程序中将
aspnet:UseTaskFriendlySynchronizationContext
设置为true。

我将尝试您的建议。但是,如果我使用SQL Server身份验证来订阅SQL查询通知,为什么当前用户身份很重要。也许我不明白它是怎么工作的。。。另外,如果您怀疑是这种情况,我希望SqlDependency.Start()每次都会失败,但在抛出异常之前,它似乎可以运行几次操作/分钟。我同意您的看法,因为
SqlDependency.Start()
与提供所有所需信息的connexionString连接,因此不需要标识。但是在堆栈跟踪中,我看到System.Runtime.Remoting.Proxies,所以我猜远程处理部分存在模拟问题,这导致调用失败。是的,我也在考虑这个问题。通知实际上是如何从SQL Server传递到订阅服务器的?使用远程处理?这意味着要使SqlDependency正常运行,它需要的不仅仅是一个连接字符串。。。我们的IIS服务器配置为使用Windows身份验证和ASP.NET模拟,但没有一个应用程序用户可以访问用作背板的SQL Server。我不认为SQL Service Broker的内部部分是基于远程处理的,我认为它更与基础架构相关(可能是负载平衡或类似的内容). 无论如何,尝试在调用之前检查您的身份,如果在发生此异常时它为null,或者如果它在工作调用和中断调用之间变化,那么您将发现问题。然后你必须传播它。