Мы загружаем документы, хранящиеся в 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 в память?