Données FILESTREAM

Télécharger ADO.NET

L'attribut de stockage FILESTREAM est destiné aux données binaires (BLOB) stockées dans une colonne varbinary(max). Avant FILESTREAM, le stockage de données binaires nécessitait un traitement spécial. Les données non structurées, telles que les documents texte, les images et les vidéos, sont souvent stockées en dehors de la base de données, ce qui rend difficile leur gestion.

Notes

Vous devez installer .NET Framework 3.5 SP1 (ou version ultérieure) ou .NET Core pour travailler avec des données FILESTREAM à l’aide de SqlClient.

Si vous spécifiez l’attribut FILESTREAM sur une colonne varbinary(max), SQL Server stocke les données sur le système de fichiers NTFS local plutôt que dans le fichier de base de données. Même si elles sont stockées séparément, vous pouvez utiliser les mêmes instructions Transact-SQL prises en charge pour utiliser les données varbinary(max) stockées dans la base de données.

Prise en charge de SqlClient pour FILESTREAM

Le fournisseur de données Microsoft SqlClient pour SQL Server, Microsoft.Data.SqlClient, prend en charge la lecture et l’écriture vers les données FILESTREAM en utilisant la classe SqlFileStream définie dans l’espace de noms System.Data.SqlTypes. SqlFileStream hérite de la classe Stream, qui fournit des méthodes pour lire et écrire dans des flux de données. La lecture depuis un flux transfère des données du flux vers une structure de données, comme un tableau d’octets. L’écriture transfère les données de la structure de données dans un flux.

Créer la table SQL Server

Les instructions Transact-SQL suivantes créent une table nommée employees et y insèrent une ligne de données. Une fois que vous avez activé le stockage FILESTREAM, vous pouvez utiliser cette table avec les exemples de code qui suivent. Les liens vers les ressources de la documentation en ligne de SQL Server figurent à la fin de cette rubrique.

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

Exemple : lecture, remplacement et insertion de données FILESTREAM

L’exemple de code suivant montre comment lire les données à partir d'un fichier FILESTREAM. Le code obtient le chemin d’accès logique au fichier, en affectant à FileAccess la valeur Read et à FileOptions la valeur SequentialScan. Le code lit ensuite les octets de SqlFileStream dans la mémoire tampon. Les octets sont alors écrits dans la fenêtre de la console.

L’exemple montre également comment écrire des données dans un fichier FILESTREAM dans lequel toutes les données existantes sont remplacées. Le code obtient le chemin d’accès logique au fichier et crée le SqlFileStream, en affectant à FileAccess la valeur Write et à FileOptions la valeur SequentialScan. Un seul octet est écrit dans le SqlFileStream, en remplaçant toutes les données dans le fichier.

L’exemple illustre aussi comment écrire des données dans un fichier FILESTREAM en utilisant la méthode Seek pour ajouter des données à la fin du fichier. Le code obtient le chemin d’accès logique au fichier et crée le SqlFileStream, en affectant à FileAccess la valeur ReadWrite et à FileOptions la valeur SequentialScan. Le code utilise la méthode Seek pour rechercher jusqu’à la fin du fichier, en ajoutant un octet unique au fichier existant.

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

        }
    }
}

Pour obtenir un autre exemple, consultez Guide pratique pour stocker et récupérer des données binaires dans une colonne de flux de fichiers.

Ressources dans la documentation en ligne de SQL Server

La documentation complète relative à FILESTREAM se trouve dans les sections suivantes de la Documentation en ligne de SQL Server.

Article Description
FILESTREAM (SQL Server) Explique quand utiliser le stockage FILESTREAM et comment il intègre le moteur de base de données SQL Server avec un système de fichiers NTFS.
Créer des applications clientes pour les données FILESTREAM Décrit les fonctions de l’API Windows permettant d’utiliser des données FILESTREAM.
Utilisation de FILESTREAM avec d’autres fonctionnalités SQL Server Fournit des considérations, instructions et limitations pour utiliser les données FILESTREAM avec d’autres fonctionnalités de SQL Server.

Étapes suivantes