Dados do FILESTREAM
O atributo de armazenamento FILESTREAM é para dados binários (BLOB) armazenados em uma varbinary(max)
coluna. Antes do FILESTREAM, o armazenamento de dados binários exigia tratamento especial. Dados não estruturados, como documentos de texto, imagens e vídeos, geralmente são armazenados fora do banco de dados, o que dificulta seu gerenciamento.
Observação
Você deve instalar o .NET Framework 3.5 SP1 (ou posterior) para trabalhar com os dados do FILESTREAM usando o SqlClient.
Especificar o atributo FILESTREAM em uma coluna varbinary(max)
faz com que o SQL Server armazene os dados no sistema de arquivos NTFS local em vez de no arquivo de banco de dados. Embora seja armazenado separadamente, você pode usar as mesmas instruções Transact-SQL que são compatíveis com o trabalho com dados varbinary(max)
que está armazenado no banco de dados.
Suporte do SqlClient para FILESTREAM
O Provedor de Dados .NET Framework para SQL Server, System.Data.SqlClient, dá suporte à leitura e à gravação em dados FILESTREAM usando a classe SqlFileStream definida no namespace System.Data.SqlTypes. O SqlFileStream
herda da classe Stream, que fornece métodos para leitura e gravação em fluxos de dados. A leitura de um fluxo transfere dados do fluxo para uma estrutura de dados, como uma matriz de bytes. A gravação transfere os dados da estrutura de dados para um fluxo.
Criando a tabela SQL Server
As instruções Transact-SQL a seguir criam uma tabela denominada employees e insere uma linha de dados. Depois de habilitar o armazenamento de FILESTREAM, você pode usar essa tabela em conjunto com os exemplos de código a seguir.
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, substituindo e inserir dados FILESTREAM
A amostra a seguir demonstra como ler dados de um FILESTREAM. O código obtém o caminho lógico para o arquivo, configurando o FileAccess
como Read
e o FileOptions
como SequentialScan
. Em seguida, o código lê os bytes de SqlFileStream no buffer. Então, os bytes são gravados na janela do console.
A amostra a seguir demonstra como gravar dados em um FILESTREAM em que todos os dados existentes são substituídos. O código obtém o caminho lógico para o arquivo e cria o SqlFileStream
, configurando o FileAccess
como Write
e o FileOptions
como SequentialScan
. Um byte é gravado no SqlFileStream
, substituindo todos os dados no arquivo.
O exemplo também demonstra como gravar dados em um FILESTREAM usando o método Seek para acrescentar dados ao final do arquivo. O código obtém o caminho lógico para o arquivo e cria o SqlFileStream
, configurando o FileAccess
como ReadWrite
e o FileOptions
como SequentialScan
. O código usa o método Seek para buscar até o final do arquivo, acrescentando um byte ao arquivo existente.
using System;
using System.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("...");
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 obter outro exemplo, confira Como armazenar e buscar dados binários em uma coluna de fluxo de arquivos.
Recursos de documentos do SQL Server
A documentação completa do FILESTREAM está localizada nas seguintes seções da documentação do SQL Server.
Tópico | Descrição |
---|---|
FILESTREAM (SQL Server) | Descreve quando usar o armazenamento FILESTREAM e como ele integra o Mecanismo de Banco de Dados do SQL Server com um sistema de arquivos NTFS. |
Criar aplicativos clientes para dados FILESTREAM | Descreve as funções da API do Windows para trabalhar usando dados FILESTREAM. |
FILESTREAM e outros recursos do SQL Server | Fornece considerações, diretrizes e limitações para usar dados FILESTREAM com outros recursos do SQL Server. |