9

I'd like to know if I can add SignalR messages directly to the SignalR SQL Backplane (from SQL) so I don't have to use a SignalR client to do so.

My situation is that I have an activated stored procedure for a SQL Service Broker queue, and when it fires, I'd like to post a message to SignalR clients. Currently, I have to receive the message from SQL Service Broker in a seperate process and then immediately re-send the message with a SignalR hub.

I'd like my activated stored procedure to basically move the message directly onto the SignalR SQL Backplane.

4

2 に答える 2

1

はいといいえ。可能かどうかを判断するために、ローカルホストで小さな実験をセットアップしました。適切にフォーマットされていれば、可能です。

さて、[SignalR]スキーマについて一言。次の 3 つのテーブルが生成されます。

[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

そうです、最後の列を複製しPayloadIdましたが、新しいレコードの (をインクリメントし、 の値として[Messages_0_Id]inを入力したことを除きます。レコードを追加した直後に、接続されたクライアントに新しいメッセージが送信されました。これは ID 列ではないことに注意してください。 、したがって、手動でインクリメントする必要があり、インクリメントされた値を の唯一のレコードにコピーする必要があります。そうしないと、Signalr SQL エラーが原因で Signalr クライアントが接続できなくなります。GETDATE()InsertedOnPayloadId[Messages_0_Id]

ここでの秘訣は、[ペイロード] 列を適切に設定することです。表をざっと見てみると、おそらくバイナリ シリアル化されていることがわかります。私は 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();
  }
}

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);
}

そのため、純粋な SQL を使用してストアド プロシージャに再実装することはほぼ不可能です。SQL Server で実行する必要がある場合は、SQL CLR 関数を使用することをお勧めします。ただし、クラス ライブラリを使用するのは簡単ですが、長期的に手間を減らしたい場合は、Visual Studio で SQL Server プロジェクトを作成することをお勧めします。これにより、最新のクラス ライブラリを手動で SQL Server に再コピーするよりもはるかに簡単に、CLR 関数を自動的に展開できます。このページでは、その方法について詳しく説明します。

于 2016-11-12T05:36:16.730 に答える