我正在编写一个控制台应用程序,它必须通过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
我的问题是网络服务只接收第一块数据,例如如果CHUNK_ROWS_COUNT = 5则它只接收5行数据。 (我知道这不是HttpWebRequest将生成的块的大小)。
我唯一的猜测是我通过流发送了一些序列化数据包,每个数据包都被一些序列化头封装,因此Web服务中的反序列化过程只能找到并解封第一个,但这只是一个想法,我不知道如何以不同的方式做到这一点。我无法序列化整个内容并将其写入块中,因为整个内容不适合内存。
有什么建议吗?
提前多多感谢
答案 0 :(得分:0)
我不确定您是否可以使用手动HttpWebRequest在WCF中执行此操作。 WCF将自己处理块,不要重新发明轮子。
一些有趣的文章:不要忘记在wcf config
中更改阅读器配额