kikki's tech note

技術ブログです。UnityやSpine、MS、Javaなど技術色々について解説しています。

SQL ServerのFileStreamデータ型をC#で扱うには

本章では、SQL Serverの機能の一つ、「FileStream」をC#での扱い方について共有します。

FileStreamとは

FileStreamは、SQL Serverにテキストファイルや画像ファイル、動画ファイルといった、ファイルサイズが大きいデータ(以後、BLOBデータとする)を高パフォーマンスで扱うための仕組みです。
以下に、公式リンクの紹介を掲載します。

FILESTREAM は、varbinary(max) BLOB (バイナリ ラージ オブジェクト) データをファイル システム上のファイルとして格納することにより、SQL Server データベース エンジンと NTFS ファイル システムを統合します。
FILESTREAM の概要

従来の方法では、データベースにBLOBデータを保存すると、データサイズに比例して読み込みに時間がかかっていました。
しかしFileStreamを利用することで、データサイズに比例することなく読み込めます。
blogs.msdn.com

それでは実際に、データベースにテーブルを用意して、確認しましょう。

データベースでの準備・使い方

FileStreamに必要なカラムが2種類あります。

  • 一意であることを保証した、UNIQUEIDENTIFIER型カラム
  • BLOBデータを格納する、VARBINARY(max)型カラム

テーブルを作成するクエリを以下に示します。

CREATE TABLE [dbo].[HogeHoge]
(
    [Id] INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
    [DocumentId] UNIQUEIDENTIFIER ROWGUIDCOL NOT NULL UNIQUE,
    [DocumentData] VARBINARY(max) FILESTREAM NULL
);

テーブル作成時の注意点として、UNIQUEIDENTIFIER型カラムがGUID値として常に一意であることを保証する、「ROWGUIDCOL」プロパティを追加する必要があります。
上記プロパティがないと、プログラム側でBLOBデータを取得できません。

次に、データを挿入するクエリを以下に示します。

INSERT
INTO
    [dbo].[HogeHoge]
(
    [DocumentId],
    [DocumentData]
)
VALUES
(
    NEWID(),
    CAST(@DocumentData AS VARBINARY(MAX))
);

※「@DocumentData」は、C#上で設定するbyte配列型のデータです。

最後に、BLOBデータを取得する際に利用するクエリを以下に示します。

SELECT
    [DocumentId],
    GET_FILESTREAM_TRANSACTION_CONTEXT() AS [DocumentData],
    [DocumentData].PathName() AS DocumentPath
FROM
    [dbo].[HogeHoge]
;

ここでの注意点は、「GET_FILESTREAM_TRANSACTION_CONTEXT()」を利用して、プログラム側で実際のファイルデータにアクセスするための権限を取得する必要があります。
また、「PathName()」を利用して、ファイルのパスを取得します。

C#での実装

C#でFileStreamを扱う際の注意点として、必ずトランザクション内でBLOBデータを取得する必要があります。

C#でFileStreamのデータを取得する際のアクセス方法について、以下に示します。

dac.BeginTran(); // dacはご自身で利用されているDAOのトランザクションを利用
var hogehoge = dac.Select("SELECT********"); // 上述のSELECT文を使って、ご自身で利用されているDAOのクエリ発行を利用
var record = hogehoge.Read();//SELECTでデータをエンティティにマッピング
using (var sfs = new SqlFileStream(record.DocumentPath, record.DocumentData, FileAccess.Read)) // SqlFileStreamクラスを利用
{
    var buffer = new byte[(int)sfs.Length];
    sfs.Read(buffer, 0, buffer.Length);
    sfs.Close();
    return buffer; // byte配列データを取得
}

筆休め

SQL ServerにFileStreamができたことで、パフォーマンスについて実装後に大きく懸念することなく、ファイルデータのやり取りが容易になりました。
SQL Serverでは、SQL Server2012で新たにFileTableを用意し、実装者はもちろん運用・保守を担当する人にとっても、FileStreamを積極的に利用できる状況になっています。
是非、FileStreamを利用してみてください。

以上、「SQL ServerのFileStreamデータ型をC#で扱うには」でした。


※無断転載禁止 Copyright (C) kikkisnrdec All Rights Reserved.