Мы загружаем документы, хранящиеся на SQL Server, используя FileStream из службы WCF, передавая объект SqlFileStream клиенту.Чтобы это работало, мы оставляем транзакцию и соединение с БД в сервисе открытым.Мы закрываем SqlFileStream в клиенте.
'Service
Public Function GetDokumentStream(dokumentId As Integer) As System.IO.Stream Implements IDataService.GetDokumentStream
Dim cnx = New SqlConnection(...)
cnx.Open()
Dim tran = cnx.BeginTransaction()
Dim cmd As New SqlCommand("Select Dokument.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT() from Dokument where ID= @ID", cnx, tran)
cmd.Parameters.AddWithValue("ID", dokumentId)
Using rdr = cmd.ExecuteReader()
If rdr.Read() Then
Dim pathName = rdr(0).ToString()
Dim context = CType(rdr(1), Byte())
Dim sqlFileStream As New SqlFileStream(pathName, context, IO.FileAccess.Read)
Return sqlFileStream
Else
'...
End If
End Using
'Client
Dim sqlFileStream = _satDataService.GetDokumentStream(dokumentInfo.DokumentID)
Using fileStream As New IO.FileStream(fileName, IO.FileMode.OpenOrCreate)
sqlFileStream.CopyTo(fileStream)
sqlFileStream.Close()
End Using
Должны ли мы реализовать что-либо для ручного закрытия соединения в службе или инфраструктура WCF очищается автоматически?Можно ли закрыть возвращаемый поток в клиенте или лучше создать сложный тип для потока, реализующего IDisposable?
В качестве альтернативы мы можем скопировать SQLFileStream в MemoryStrean, закрыть соединение и вернуть поток памяти:
Using cnx = New SqlConnection(...)
cnx.Open()
Using tran = cnx.BeginTransaction()
Dim cmd As New SqlCommand("Select Dokument.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT() from Dokument where ID= @ID", cnx,
tran)
cmd.Parameters.AddWithValue("ID", dokumentId)
Using rdr = cmd.ExecuteReader()
If rdr.Read() Then
Dim pathName = rdr(0).ToString()
Dim context = CType(rdr(1), Byte())
Dim context1 = rdr(1)
Dim sqlFileStream As New SqlFileStream(pathName, context, IO.FileAccess.Read)
sqlFileStream.CopyTo(memoryStream)
_trace.InfoFormat("Returning file {0} size {1}bytes", pathName, memoryStream.Length)
memoryStream.Position = 0
Return memoryStream
Else
Throw New ApplicationException("Dokument File not found")
End If
End Using
End Using
End Using
Использует ли это решение больше памяти на сервере, чем напрямую, возвращая SqlFileStream?Или WCF внутренне копирует SqlFileStream в память в любом случае?