FILESTREAM-Daten
Das FILESTREAM-Speicherattribut ist für binäre (BLOB-)Daten vorgesehen, die in einer varbinary(max)
-Spalte gespeichert sind. Vor FILESTREAM erforderte das Speichern von Binärdaten eine spezielle Verarbeitung. Unstrukturierte Daten, wie z. B. Textdokumente, Bilder und Videos, werden oft außerhalb der Datenbank gespeichert und sind daher schwierig zu verwalten.
Hinweis
Sie müssen .NET Framework 3.5 SP1 (oder höher) installieren, um mithilfe von SqlClient mit FILESTREAM-Daten zu arbeiten.
Wenn das FILESTREAM-Attribut für eine varbinary(max)
-Spalte festgelegt ist, werden die Daten von SQL Server im lokalen NTFS-Dateisystem und nicht in der Datenbankdatei gespeichert. Obwohl die Speicherung separat erfolgt, können dieselben Transact-SQL-Anweisungen verwendet werden, die für das Arbeiten mit in der Datenbank gespeicherten varbinary(max)
-Daten unterstützt werden.
SqlClient-Unterstützung für FILESTREAM
Der .NET Framework Data Provider für SQL Server, System.Data.SqlClient, unterstützt das Lesen und Schreiben von FILESTREAM-Daten unter Verwendung der SqlFileStream-Klasse, die im System.Data.SqlTypes-Namespace definiert ist. SqlFileStream
erbt von der Stream-Klasse, die Methoden zum Lesen und Schreiben von Datenströmen zur Verfügung stellt. Beim Lesen aus einem Datenstrom werden Daten aus dem Datenstrom in eine Datenstruktur, z. B. ein Array von Bytes, übertragen. Beim Schreiben werden die Daten aus der Datenstruktur in einen Datenstrom übertragen.
Erstellen der SQL Server-Tabelle
Mit den folgenden Transact-SQL-Anweisungen wird eine Tabelle mit dem Namen „employees“ erstellt und eine Datenzeile eingefügt. Sobald Sie die FILESTREAM-Speicherung aktiviert haben, können Sie diese Tabelle in Verbindung mit den folgenden Codebeispielen verwenden.
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
Beispiel: Lesen, Überschreiben und Einfügen von FILESTREAM-Daten
Das folgende Beispiel veranschaulicht, wie Daten aus einem FILESTREAM gelesen werden können. Der Code ruft den logischen Pfad zur Datei ab, wobei FileAccess
auf Read
und FileOptions
auf SequentialScan
festgelegt wird. Der Code liest dann die Bytes aus dem SqlFileStream in den Puffer ein. Die Bytes werden anschließend in das Konsolenfenster geschrieben.
Das Beispiel veranschaulicht auch, wie Daten in einen FILESTREAM geschrieben werden, wobei alle vorhandenen Daten überschrieben werden. Der Code ruft den logischen Pfad zur Datei ab und erstellt SqlFileStream
, wobei FileAccess
auf Write
und FileOptions
auf SequentialScan
festgelegt wird. Ein einzelnes Byte wird in SqlFileStream
geschrieben, wobei alle Daten in der Datei ersetzt werden.
Im Beispiel wird außerdem dargestellt, wie Daten unter Verwendung der „Seek“-Methode in einen FILESTREAM geschrieben werden, wobei die Daten ans Ende der Datei angehängt werden. Der Code ruft den logischen Pfad zur Datei ab und erstellt SqlFileStream
, wobei FileAccess
auf ReadWrite
und FileOptions
auf SequentialScan
festgelegt wird. Der Code verwendet die Seek-Methode, um das Ende der Datei zu suchen, wobei ein einzelnes Byte an die vorhandene Datei angefügt wird.
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();
}
}
}
}
Ein weiteres Beispiel finden Sie unter Speichern und Abrufen von Binärdaten in einer FILESTREAM-Spalte.
SQL Server-Dokumentationsressourcen
Die vollständige Dokumentation zu FILESTREAM finden Sie in den folgenden Abschnitten der SQL Server-Dokumentation.
Thema | Beschreibung |
---|---|
FILESTREAM (SQL Server) | Beschreibt, wann FILESTREAM-Speicher verwendet wird und wie dieser die SQL Server-Datenbank-Engine in ein NTFS-Dateisystem integriert. |
Erstellen von Clientanwendungen für FILESTREAM-Daten | Beschreibt die Windows-API-Funktionen für das Arbeiten mit FILESTREAM-Daten. |
FILESTREAM und andere SQL Server-Funktionen | Enthält Überlegungen, Leitlinien und Einschränkungen für die Verwendung von FILESTREAM-Daten mit anderen Features von SQL Server. |