Web サービスを介してデータを送信することにより、大きな SQL テーブルをデータベースから別のデータベースにコピーする必要があるコンソール アプリケーションを作成しています。テーブルは非常に大きくなる可能性があり、完全にメモリに格納することはできません (そしてすべきではありません) ため、DataReader を使用してデータを順番に読み取り、それを Web サービスにストリーミングしたいと考えていました。
これを行うために、Web サービスを次のように宣言します。
<OperationContract()>
<WebInvoke(UriTemplate:="{Id}/SendData", method:="PUT", BodyStyle:=WebMessageBodyStyle.WrappedRequest)>
Sub UploadData(ByVal Id As String, ByVal DataStream As Stream)
私のコンソール アプリケーションでは、次のようにリクエストを作成しています。
Dim tRequest As HttpWebRequest = HttpWebRequest.Create(URL_WEBSERVICES & "DataLoad/" & _Id & "/SendData")
tRequest.SendChunked = True
tRequest.Method = "PUT"
tRequest.ContentType = "application/octet-stream"
次に、リクエスト ストリームを開き、次のようにデータを書き込みます。
While tSqlReader.Read
' Check if a new chunk of data must be created
If tRows Is Nothing Then
tRows = New List(Of Object)
End If
' Fill chunk with data
tRowValues = New Object(tSqlReader.FieldCount - 1) {}
tSqlReader.GetValues(tRowValues)
tRows.Add(tRowValues)
' Check if chunk is full and must be sent
If tRows.Count = CHUNK_ROWS_COUNT Then
' Write data to the request stream
tDataChunk = SerializeToByteArray(tRows)
tStream.Write(tDataChunk, 0, tDataChunk.Length)
tRows = Nothing
tDataChunk = Nothing
End If
End While
' Write final data to the request stream
If tRows IsNot Nothing Then
tDataChunk = SerializeToByteArray(tRows)
tStream.Write(tDataChunk, 0, tDataChunk.Length)
End If
次に、リクエスト ストリームを閉じて、tRequest.GetResponse() を呼び出します。
SerializeToByArray は次の関数です。
Private Function SerializeToByteArray(ByVal pObject As Object) As Byte()
If pObject Is Nothing Then Return Nothing
Dim tBinaryFormatter As New Runtime.Serialization.Formatters.Binary.BinaryFormatter
Dim tMemoryStream As New MemoryStream()
tBinaryFormatter.Serialize(tMemoryStream, pObject)
Return tMemoryStream.ToArray
End Function
私の問題は、Web サービスがデータの最初のチャンクしか受信しないことです。たとえば、CHUNK_ROWS_COUNT = 5 の場合、5 行のデータしか受信しません。(これは、HttpWebRequest が作成するチャンクのサイズではないことを認識しています)。
私の唯一の推測は、ストリームを介していくつかのシリアル化されたデータ パックを送信し、それぞれがいくつかのシリアル化ヘッダーによってカプセル化されているため、Web サービスの逆シリアル化プロセスは最初のもののみを見つけてカプセル化解除することですが、それは単なるアイデアであり、私は別の方法で行う方法がわかりません。コンテンツ全体がメモリに収まらないため、コンテンツ全体をシリアル化してチャンクで送信することはできません。
何かアドバイス?
事前にどうもありがとう