FILESTREAM データ

ADO.NET のダウンロード

FILESTREAM ストレージ属性は、varbinary(max) 列に格納されるバイナリ (BLOB) データに対応しています。 FILESTREAM 以前は、バイナリデータの格納に特別な処理が必要でした。 テキスト ドキュメント、イメージ、ビデオなどの非構造化データはデータベース外に保存されることが多く、そのために管理が困難でした。

Note

SqlClient を使用して FILESTREAM データを操作するには、.NET Framework 3.5 SP1 (またはそれ以降) または .NET Core をインストールする必要があります。

varbinary(max) 列に FILESTREAM 属性を指定すると、SQL Server ではデータはデータベース ファイルではなくローカルの NTFS ファイル システムに保存されます。 データは個別に保存されますが、データベースに保存されている varbinary(max) データの操作をサポートしている、同じ Transact-SQL ステートメントを使用できます。

SqlClient による FILESTREAM のサポート

Microsoft SqlClient Data Provider for SQL Server Microsoft.Data.SqlClient は、System.Data.SqlTypes 名前空間に定義された SqlFileStream クラスを使用して、FILESTREAM データからの読み取りと FILESTREAM データへの書き込みをサポートします。 SqlFileStreamStream クラスを継承します。このクラスは、データのストリームへの読み込みと書き込みを行うためのメソッドを提供します。 ストリームからの読み取りでは、データをストリームからバイト配列などのデータ構造に転送します。 書き込みを行うと、データはデータ構造からストリームに転送されます。

SQL Server テーブルの作成

次の Transact-SQL ステートメントによって、"employees" という名前のテーブルが作成され、データ行が挿入されます。 FILESTREAM ストレージを有効にしたら、このテーブルを以下のコード例と併せて使用できます。 SQL Server オンライン ブックの関連トピックへのリンクは、この記事の末尾に記載されています。

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 からデータを読み取る方法を示します。 このコードでは、ファイルへの論理パスを取得し、FileAccessRead に、FileOptionsSequentialScan に設定します。 次に、コードが SqlFileStream からバッファーにバイトを読み取ります。 次に、バイトがコンソール ウィンドウに書き込まれます。

さらに、このサンプルでは、既存のすべてのデータが上書きされる FILESTREAM にデータを書き込む方法も示しています。 このコードでは、ファイルへの論理パスを取得し、SqlFileStream を作成して、FileAccessWrite に、FileOptionsSequentialScan に設定します。 1 バイトが SqlFileStream に書き込まれ、ファイル内のすべてのデータが置き換えられます。

このサンプルでは、Seek メソッドを使用してファイルの末尾にデータを追加することによって、データを FILESTREAM に書き込む方法も示します。 このコードでは、ファイルへの論理パスを取得し、SqlFileStream を作成して、FileAccessReadWrite に、FileOptionsSequentialScan に設定します。 このコードは、Seek メソッドを使用してファイルの末尾までシークし、既存のファイルに 1 バイトを追加します。

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

        }
    }
}

別のサンプルについては、「ファイル ストリーム列にバイナリ データをフェッチおよび格納する方法」を参照してください。

SQL Server オンライン ブックのリソース

FILESTREAM の詳細なドキュメントは、SQL Server オンライン ブックの次のセクションにあります。

[アーティクル] 説明
FILESTREAM (SQL Server) FILESTREAM ストレージを使用するタイミングと、SQL Server データベース エンジンと NTFS ファイル システムを統合する方法について説明します。
FILESTREAM データ用のクライアント アプリケーションの作成 FILESTREAM データを操作するための Windows API 関数について説明します。
FILESTREAM と SQL Server のその他の機能 FILESTREAM データを SQL Server の他の機能で使用する場合の考慮事項、ガイドライン、および制限事項について説明します。

次のステップ