Поделиться через


Данные FILESTREAM в SQL Server 2008 (ADO.NET)

В SQL Server 2008 для двоичных (BLOB) данных, хранящихся в столбце varbinary(max), появился новый атрибут хранилища FILESTREAM. В SQL Server всегда можно было хранить двоичные данные, однако для работы с ними требовалась специальная обработка. Неструктурированные данные, например текстовые документы, изображения и видеоролики, зачастую хранятся вне базы данных, что затрудняет работу с ними.

ПримечаниеПримечание

Для работы с данными FILESTREAM через SqlClient необходимо установить .NET Framework 3.5 с пакетом обновления 1 (SP1) или более поздней версии.

При указании для столбца varbinary(max) атрибута FILESTREAM сервер SQL Server сохраняет данные не в файле базы данных, а в файловой системе NTFS на локальном компьютере. Хотя эти данные хранятся отдельно, для работы с ними можно использовать те же инструкции Transact-SQL, что и для данных varbinary(max), хранящихся в базе данных.

Поддержка атрибута FILESTREAM в SqlClient

Поставщик данных .NET Framework для SQL Server (System.Data.SqlClient) поддерживает чтение и запись данных FILESTREAM с помощью класса SqlFileStream, определенного в пространстве имен System.Data.SqlTypes. Класс SqlFileStream является производным от класса System.IO.Stream, который содержит методы для чтения и записи потоков данных. При чтении из потока данные передаются в структуру данных, например в массив байтов. При записи данные передаются из структуры данных в поток.

Создание таблицы SQL Server

Приведенная ниже инструкция Transact-SQL создает таблицу employees и вставляет в нее строку данных. После включения атрибута FILESTREAM эту таблицу можно использовать в приведенных ниже примерах кода. Ссылки на ресурсы электронной документации по SQL Server 2008 приведены в конце данного раздела.

CREATE TABLE employees
(
  EmployeeId INT  NOT NULL  PRIMARY KEY,
  Photo VARBINARY(MAX) FILESTREAM  NULL,
  RowGuid UNIQUEIDENTIFIER  NOT NULL  ROWGUIDCOL
  UNIQUE DEFAULT NEWID()
)
GO
Insert into employees
Values(1, 0x00, default)
GO

Пример чтения данных FILESTREAM

В приведенном ниже фрагменте кода демонстрируется чтение данных из потока FILESTREAM. В коде определяется логический путь к файлу, свойству FileAccess присваивается значение Read, а свойству FileOptions — значение SequentialScan. Затем в коде считываются в буфер байты данных из потока SqlFileStream. Эти байты данных затем выводятся в окно консоли.

using (SqlConnection connection = new SqlConnection(
    connStringBuilder.ToString()))
{
    connection.Open();
    SqlCommand command = new SqlCommand("", connection);

    SqlTransaction tran = connection.BeginTransaction(
       System.Data.IsolationLevel.ReadCommitted);
    command.Transaction = tran;

    command.CommandText = 
        "select Top(1) Photo.PathName(), " 
        + "GET_FILESTREAM_TRANSACTION_CONTEXT () from employees";
    using (SqlDataReader reader = command.ExecuteReader())
    {
        while (reader.Read())
        {
            // Get the pointer for the file
            string path = reader.GetString(0);
            byte[] transactionContext = reader.GetSqlBytes(1).Buffer;

            // Create the SqlFileStream
            FileStream fileStream = new SqlFileStream(path,
            (byte[])reader.GetValue(1),
                FileAccess.Read,
                FileOptions.SequentialScan, 0);

            // Read the contents as bytes and write them to the console
            for (long index = 0; index < fileStream.Length; index++)
            {
                Console.Write(fileStream.ReadByte());
            }
            fileStream.Close();
        }
    }
    tran.Commit();
}

Пример перезаписи данных FILESTREAM

В приведенном ниже фрагменте кода демонстрируется запись данных в поток FILESTREAM с перезаписью всех существующих данных. В коде определяется логический путь к файлу, создается поток SqlFileStream, свойству FileAccess присваивается значение Write, а свойству FileOptions — значение SequentialScan. В поток SqlFileStream записывается один байт, заменяющий все данные в файле.

using (SqlConnection connection = new SqlConnection(
    connStringBuilder.ToString()))
{
    connection.Open();

    SqlCommand command = new SqlCommand("", connection);
    command.CommandText = "select Top(1) Photo.PathName(), "
    + "GET_FILESTREAM_TRANSACTION_CONTEXT () from employees";

    SqlTransaction tran = connection.BeginTransaction(
        System.Data.IsolationLevel.ReadCommitted);
    command.Transaction = tran;

    using (SqlDataReader reader = command.ExecuteReader())
    {
        while (reader.Read())
        {
            // Get the pointer for file 
            string path = reader.GetString(0);
            byte[] transactionContext = reader.GetSqlBytes(1).Buffer;

            // Create the SqlFileStream
            FileStream fileStream = new SqlFileStream(path,
                (byte[])reader.GetValue(1),
                FileAccess.Write,
                FileOptions.SequentialScan, 0);

            // Write a single byte to the file. This will
            // replace any data in the file.
            fileStream.WriteByte(0x01);

            fileStream.Close();
        }
    }
    tran.Commit();
}

Пример вставки данных FILESTREAM

В приведенном ниже примере кода демонстрируется запись данных в поток FILESTREAM с использованием метода Seek для добавления данных в конец файла. В коде определяется логический путь к файлу, создается поток SqlFileStream, свойству FileAccess присваивается значение ReadWrite, а свойству FileOptions — значение SequentialScan. Для поиска конца файла в коде используется метод Seek, после чего в конец файла добавляется один байт.

using (SqlConnection connection = new SqlConnection(
    connStringBuilder.ToString()))
{
    connection.Open();

    SqlCommand command = new SqlCommand("", connection);
    command.CommandText = "select Top(1) Photo.PathName(), "
    + "GET_FILESTREAM_TRANSACTION_CONTEXT () from employees";

    SqlTransaction tran = connection.BeginTransaction(
        System.Data.IsolationLevel.ReadCommitted);
    command.Transaction = tran;

    using (SqlDataReader reader = command.ExecuteReader())
    {
        while (reader.Read())
        {
            // Get the pointer for file
            string path = reader.GetString(0);
            byte[] transactionContext = reader.GetSqlBytes(1).Buffer;

            FileStream fileStream = new SqlFileStream(path,
                (byte[])reader.GetValue(1),
                FileAccess.ReadWrite,
                FileOptions.SequentialScan, 0);

            // Seek to the end of the file
            fs.Seek(0, SeekOrigin.End);

            // Append a single byte 
            fileStream.WriteByte(0x01);
            fileStream.Close();
        }
    }
    tran.Commit();
}

Ресурсы электронной документации по SQL Server

Полная документация по FILESTREAM содержится в указанных ниже разделах электронной документации по SQL Server 2008.

Раздел

Описание

Разработка и реализация хранилища FILESTREAM

Приводятся ссылки на документацию по атрибуту FILESTREAM и связанные с ним разделы.

Общие сведения об атрибуте FILESTREAM

Приводятся сведения о том, когда необходимо использовать хранилище FILESTREAM; также описывается интеграция ядра СУБД SQL Server и файловой системы NTFS.

Приступая к работе с хранилищем FILESTREAM

Описывается включение хранилища FILESTREAM для экземпляра SQL Server, создание базы данных и таблицы, в которой будут храниться данные FILESTREAM, а также работа со строками, содержащими данные FILESTREAM.

Использование хранилища FILESTREAM в клиентских приложениях

Описываются функции API-интерфейса Win32, предназначенные для работы с данными FILESTREAM.

FILESTREAM и другие возможности SQL Server

Приводятся общие сведения, рекомендации и ограничения при использовании данных FILESTREAM совместно с другими возможностями SQL Server.

См. также

Основные понятия

Управление доступом для кода и ADO.NET

Другие ресурсы

Типы данных SQL Server и ADO.NET

Получение и изменение данных в ADO.NET

Двоичные данные и данные большого размера SQL Server (ADO.NET)