Хобрук: Ваш путь к мастерству в программировании

Каков чистый способ вернуть SQLFileStream из службы WCF?

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

02.08.2011

Ответы:


1

Вы должны сами заниматься своим подключением и транзакцией. WCF не несет ответственности за внутреннюю реализацию операции. Поток, переданный в качестве параметра или возвращенный из операции, имеет вид по умолчанию закрыт WCF.

Ваш второй пример загрузит все данные из потока в память вашего хоста службы. Это испортит цель стриминга на стороне сервиса.

02.08.2011
  • Хорошо, теперь я понимаю, как работать с потоками. Как мне самому закрыть соединение? Моя служба - InstanceContextMode.PerCall. Закрытие соединения в конце функции вызывает ошибку. Соединение сокета было прервано. 04.08.2011
  • Вы можете попытаться сделать свою службу одноразовой и закрыть соединение при вызове dispose (поставщик экземпляра по умолчанию делает это, когда экземпляр освобождается). 04.08.2011

  • 2

    Я сам столкнулся с этой проблемой и создал класс-оболочку вокруг SqlFileStream, который использует универсальную типизацию и отражение, чтобы вы могли сопоставить строку с типом и получить доступ к столбцу FILESTREAM.

    Вам не нужно писать какие-либо операторы SQL, все они генерируются внутри с использованием информации сопоставления.

    Он также обертывает соединение и транзакцию, так что после удаления потока транзакция фиксируется, а соединение удаляется, что делает безопасным возврат из службы WCF.

    Он доступен на https://github.com/RupertAvery/WrappedSqlFileStream.

    04.03.2016
    Новые материалы

    Dall-E 2: недавние исследования показывают недостатки в искусстве, созданном искусственным интеллектом
    DALL-E 2 — это всеобщее внимание в индустрии искусственного интеллекта. Люди в списке ожидания пытаются заполучить продукт. Что это означает для развития креативной индустрии? О применении ИИ в..

    «Очень простой» эволюционный подход к обучению с подкреплением
    В прошлом семестре я посетил лекцию по обучению с подкреплением (RL) в моем университете. Честно говоря, я присоединился к нему официально, но я редко ходил на лекции, потому что в целом я нахожу..

    Освоение информационного поиска: создание интеллектуальных поисковых систем (глава 1)
    Глава 1. Поиск по ключевым словам: основы информационного поиска Справочная глава: «Оценка моделей поиска информации: подробное руководство по показателям производительности » Глава 1: «Поиск..

    Фишинг — Упаковано и зашифровано
    Будучи старшим ИТ-специалистом в небольшой фирме, я могу делать много разных вещей. Одна из этих вещей: специалист по кибербезопасности. Мне нравится это делать, потому что в настоящее время я..

    ВЫ РЕГРЕСС ЭТО?
    Чтобы понять, когда использовать регрессионный анализ, мы должны сначала понять, что именно он делает. Вот простой ответ, который появляется, когда вы используете Google: Регрессионный..

    Не зря же это называют интеллектом
    Стек — C#, Oracle Опыт — 4 года Работа — Разведывательный корпус Мне пора служить Может быть, я немного приукрашиваю себя, но там, где я живу, есть обязательная военная служба на 3..

    LeetCode Проблема 41. Первый пропущенный положительный результат
    LeetCode Проблема 41. Первый пропущенный положительный результат Учитывая несортированный массив целых чисел, найдите наименьшее пропущенное положительное целое число. Пример 1: Input:..