Partilhar via


Dados FILESTREAM

Baixar ADO.NET

O atributo de armazenamento FILESTREAM é para dados binários (BLOB) armazenados numa coluna varbinary(max). Antes do FILESTREAM, armazenar dados binários exigia um tratamento especial. Dados não estruturados, como documentos de texto, imagens e vídeo, são frequentemente armazenados fora da base de dados, dificultando a sua gestão.

Observação

Deve instalar o .NET Framework 3.5 SP1 (ou posterior) ou o .NET Core para trabalhar com dados FILESTREAM usando SqlClient.

Especificar o atributo FILESTREAM numa coluna varbinary(max) faz com que o SQL Server armazene os dados no sistema de ficheiros NTFS local em vez de no ficheiro da base de dados. Embora esteja armazenado separadamente, pode usar as mesmas instruções Transact-SQL suportadas para trabalhar com dados do tipo varbinary(max) armazenados na base de dados.

Suporte SqlClient para FILESTREAM

O Microsoft SqlClient Data Provider para SQL Server, Microsoft.Data.SqlClient, suporta a leitura e escrita de dados FILESTREAM usando a SqlFileStream classe definida no System.Data.SqlTypes namespace. SqlFileStream herda da Stream classe, que fornece métodos para leitura e escrita em fluxos de dados. A leitura de um fluxo transfere dados do fluxo para uma estrutura de dados, como um array de bytes. A escrita transfere os dados da estrutura de dados para um fluxo.

Criação da tabela SQL Server

As seguintes instruções Transact-SQL criam uma tabela chamada funcionários e inserem uma linha de dados. Depois de ativar o armazenamento FILESTREAM, pode usar esta tabela com os exemplos de código que se seguem. Os links para recursos no SQL Server Books Online encontram-se no final deste artigo.

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

Exemplo: Ler, sobrescrever e inserir dados do FILESTREAM

O exemplo seguinte demonstra como ler dados de um FILESTREAM. O código obtém o caminho lógico para o ficheiro, definindo o FileAccess para Read e o FileOptions para SequentialScan. O código então lê os bytes do SqlFileStream para o buffer. Os bytes são então escritos na janela da consola.

O exemplo também demonstra como escrever dados num FILESTREAM em que todos os dados existentes são sobrescritos. O código obtém o caminho lógico até ao ficheiro e cria o SqlFileStream, definindo o FileAccess to Write e o FileOptions to SequentialScan. Um único byte é escrito no SqlFileStream, substituindo quaisquer dados no ficheiro.

O exemplo também demonstra como escrever dados num FILESTREAM usando o método Seek para anexar dados ao final do ficheiro. O código obtém o caminho lógico até ao ficheiro e cria o SqlFileStream, definindo o FileAccess to ReadWrite e o FileOptions to SequentialScan. O código utiliza o método Seek para procurar até ao final do ficheiro, acrescentando um único byte ao ficheiro existente.

using System;
using Microsoft.Data.SqlClient;
using System.Data.SqlTypes;
using System.Data;
using System.IO;

namespace FileStreamTest
{
    class Program
    {
        static void Main(string[] args)
        {
            SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder("server=(local);integrated security=true;Encrypt=True;database=myDB");
            ReadFileStream(builder);
            OverwriteFileStream(builder);
            InsertFileStream(builder);

            Console.WriteLine("Done");
        }

        private static void ReadFileStream(SqlConnectionStringBuilder connStringBuilder)
        {
            using (SqlConnection connection = new SqlConnection(connStringBuilder.ToString()))
            {
                connection.Open();
                SqlCommand command = new SqlCommand("SELECT TOP(1) Photo.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT() FROM employees", connection);

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

                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
                        using (Stream fileStream = new SqlFileStream(path, transactionContext, FileAccess.Read, FileOptions.SequentialScan, allocationSize: 0))
                        {
                            // Read the contents as bytes and write them to the console
                            for (long index = 0; index < fileStream.Length; index++)
                            {
                                Console.WriteLine(fileStream.ReadByte());
                            }
                        }
                    }
                }
                tran.Commit();
            }
        }

        private static void OverwriteFileStream(SqlConnectionStringBuilder connStringBuilder)
        {
            using (SqlConnection connection = new SqlConnection(connStringBuilder.ToString()))
            {
                connection.Open();

                SqlCommand command = new SqlCommand("SELECT TOP(1) Photo.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT() FROM employees", connection);

                SqlTransaction tran = connection.BeginTransaction(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
                        using (Stream fileStream = new SqlFileStream(path, transactionContext, FileAccess.Write, FileOptions.SequentialScan, allocationSize: 0))
                        {
                            // Write a single byte to the file. This will
                            // replace any data in the file.
                            fileStream.WriteByte(0x01);
                        }
                    }
                }
                tran.Commit();
            }
        }

        private static void InsertFileStream(SqlConnectionStringBuilder connStringBuilder)
        {
            using (SqlConnection connection = new SqlConnection(connStringBuilder.ToString()))
            {
                connection.Open();

                SqlCommand command = new SqlCommand("SELECT TOP(1) Photo.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT() FROM employees", connection);

                SqlTransaction tran = connection.BeginTransaction(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;

                        using (Stream fileStream = new SqlFileStream(path, transactionContext, FileAccess.ReadWrite, FileOptions.SequentialScan, allocationSize: 0))
                        {
                            // Seek to the end of the file
                            fileStream.Seek(0, SeekOrigin.End);

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

        }
    }
}

Para outro exemplo, veja Como armazenar e buscar dados binários numa coluna de fluxo de ficheiros.

Recursos em SQL Server Books Online

A documentação completa do FILESTREAM encontra-se nas secções seguintes do SQL Server Books Online.

Artigo Description
FILESTREAM (SQL Server) Descreve quando usar o armazenamento FILESTREAM e como este integra o Motor de Base de Dados SQL Server com um sistema de ficheiros NTFS.
Criar aplicativos cliente para dados FILESTREAM Descreve as funções da API do Windows para trabalhar com dados do FILESTREAM.
FILESTREAM e Outras Funcionalidades do SQL Server Fornece considerações, orientações e limitações para a utilização de dados FILESTREAM com outras funcionalidades do SQL Server.

Próximos passos