Nov*_*vox 9 sql service-broker signalr signalr-backplane
我想知道是否可以将SignalR消息直接添加到SignalR SQL背板(来自SQL),因此我不必使用SignalR客户端来执行此操作.
我的情况是我有一个SQL Service Broker队列的激活存储过程,当它触发时,我想向SignalR客户端发送一条消息.目前,我必须在单独的进程中从SQL Service Broker接收消息,然后立即使用SignalR集线器重新发送消息.
我希望我的激活存储过程基本上将消息直接移动到SignalR SQL背板上.
是和不是。我在本地主机上设置了一个小实验,以确定是否可能 - 如果格式正确,它就是可能的。
现在,谈谈[SignalR]架构。它生成三个表:
[SignalR].[Messages_0]
--this holds a list of all messages with the columns of
--[PayloadId], [Payload], and [InsertedOn]
[SignalR].[Messages_0_Id]
--this holds one record of one field - the last Id value in the [Messages_0] table
[SignalR].[Scehma]
--No idea what this is for; it's a 1 column (SchemaVersion) 1 record (value of 1) table
Run Code Online (Sandbox Code Playgroud)
是的,所以,我复制了最后一列,除了我增加了PayloadId( 对于新记录和 in[Messages_0_Id]并放入GETDATE()作为 的值InsertedOn。添加记录后,一条新消息立即进入连接的客户端。请注意,这PayloadId不是身份列,因此您必须手动递增它,并且必须将该递增的值复制到 中的唯一记录中[Messages_0_Id],否则您的信号器客户端将由于 Signalr SQL 错误而无法连接。
现在,技巧是正确填充 [Payload] 列。快速查看该表表明它可能是二进制序列化的。我不是 SQL 专家,但我很确定执行二进制序列化会很困难。如果我是对的,这是二进制序列化的源代码,位于Microsoft.AspNet.SignalR.Messaging.ScaleoutMessage:
public byte[] ToBytes()
{
using (MemoryStream memoryStream = new MemoryStream())
{
BinaryWriter binaryWriter = new BinaryWriter((Stream) memoryStream);
binaryWriter.Write(this.Messages.Count);
for (int index = 0; index < this.Messages.Count; ++index)
this.Messages[index].WriteTo((Stream) memoryStream);
binaryWriter.Write(this.ServerCreationTime.Ticks);
return memoryStream.ToArray();
}
}
Run Code Online (Sandbox Code Playgroud)
和WriteTo:
public void WriteTo(Stream stream)
{
BinaryWriter binaryWriter = new BinaryWriter(stream);
string source = this.Source;
binaryWriter.Write(source);
string key = this.Key;
binaryWriter.Write(key);
int count1 = this.Value.Count;
binaryWriter.Write(count1);
ArraySegment<byte> arraySegment = this.Value;
byte[] array = arraySegment.Array;
arraySegment = this.Value;
int offset = arraySegment.Offset;
arraySegment = this.Value;
int count2 = arraySegment.Count;
binaryWriter.Write(array, offset, count2);
string str1 = this.CommandId ?? string.Empty;
binaryWriter.Write(str1);
int num1 = this.WaitForAck ? 1 : 0;
binaryWriter.Write(num1 != 0);
int num2 = this.IsAck ? 1 : 0;
binaryWriter.Write(num2 != 0);
string str2 = this.Filter ?? string.Empty;
binaryWriter.Write(str2);
}
Run Code Online (Sandbox Code Playgroud)
因此,用纯 SQL 在存储过程中重新实现它几乎是不可能的。如果您需要在 SQL Server 上执行此操作,我建议使用SQL CLR 函数。不过,有一点值得一提 - 使用类库很容易,但如果您想长期减少麻烦,我建议在 Visual Studio 中创建一个 SQL Server 项目。这将使您能够比手动将最新的类库重新复制到 SQL Server 更轻松地自动部署 CLR 函数。本页详细讨论了如何做到这一点。