Dati FILESTREAM

L'attributo di archiviazione FILESTREAM è destinato all'uso con i dati binari (BLOB) archiviati in una colonna varbinary(max). Prima di FILESTREAM, l'archiviazione dei dati binari richiedeva una gestione speciale. I dati non strutturati, ad esempio documenti di testo, immagini e video, vengono spesso archiviati all'esterno del database e diventano difficili da gestire.

Nota

Per usare i dati FILESTREAM con SqlClient, è necessario installare .NET Framework 3.5 SP1 (o versioni successive).

Se si specifica l'attributo FILESTREAM in una colonna varbinary(max), in SQL Server i dati vengono archiviati nel file system NTFS locale anziché nel file di database. Sebbene vengano archiviati separatamente, è possibile usare le stesse istruzioni Transact-SQL supportate per l'uso di dati varbinary(max) archiviati nel database.

Supporto di SqlClient per FILESTREAM

Il provider di dati .NET Framework per SQL Server, System.Data.SqlClient, supporta la lettura e la scrittura nei dati FILESTREAM utilizzando la classe SqlFileStream definita nello spazio dei nomi System.Data.SqlTypes. SqlFileStream eredita dalla classe Stream, che specifica i metodi per la lettura e la scrittura nei flussi di dati. La lettura da un flusso trasferisce i dati dal flusso in una struttura di dati, ad esempio una matrice di byte. La scrittura trasferisce i dati dalla struttura di dati in un flusso.

Creazione di una tabella SQL Server

Le istruzioni Transact-SQL seguenti consentono di creare una tabella denominata employees e di inserire una riga di dati. Dopo aver abilitato l'archiviazione FILESTREAM, è possibile usare questa tabella insieme agli esempi di codice riportati di seguito.

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

Esempio: lettura, sovrascrittura e inserimento di dati FILESTREAM

Nell'esempio seguente viene illustrato come leggere i dati da un oggetto FILESTREAM. Il codice ottiene il percorso logico del file, impostando FileAccess su Read e FileOptions su SequentialScan. Il codice legge quindi i byte da SqlFileStream nel buffer. I byte vengono quindi scritti nella finestra della console.

L'esempio illustra anche come scrivere dati in un oggetto FILESTREAM nel quale vengono sovrascritti tutti i dati esistenti. Il codice ottiene il percorso logico del file e crea SqlFileStream, impostando FileAccess su Write e FileOptions su SequentialScan. Un singolo byte viene scritto in SqlFileStream, sostituendo tutti i dati nel file.

L'esempio dimostra inoltre come scrivere i dati in un oggetto FILESTREAM usando il metodo Seek per aggiungere i dati alla fine del file. Il codice ottiene il percorso logico del file e crea SqlFileStream, impostando FileAccess su ReadWrite e FileOptions su SequentialScan. Il codice usa il metodo Seek per cercare alla fine del file, aggiungendo un singolo byte al file esistente.

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();
            }

        }
    }
}

Per un altro esempio, vedere Come archiviare e recuperare dati binari in una colonna di flusso di file.

Risorse della documentazione di SQL Server

La documentazione completa per FILESTREAM è disponibile nelle sezioni seguenti della documentazione di SQL Server.

Argomento Descrizione
FILESTREAM (SQL Server) Spiega quando si usa l'archiviazione FILESTREAM e in che modo integra il motore di database di SQL Server con un file system NTFS.
Creazione di applicazioni client per dati FILESTREAM Descrive le funzioni dell'API Windows per l'uso dei dati FILESTREAM.
FILESTREAM e altre funzionalità di SQL Server Include considerazioni, linee guida e limitazioni per l'uso dei dati FILESTREAM con altre funzionalità di SQL Server.

Vedi anche