SQL Server 2008 中的 FILESTREAM 数据 (ADO.NET)
SQL Server 2008 为 varbinary(max) 列中存储的二进制 (BLOB) 数据引入了 FILESTREAM 存储属性。 SQL Server 始终提供存储二进制数据的功能,但使用此功能要求进行特殊处理。 非结构化的数据(例如文本文档、图像和视频)通常存储在数据库之外,从而使得难以管理此类数据。
注意 |
---|
您必须安装 .NET Framework 3.5 SP1(或更高版本)才能使用 SqlClient 处理 FILESTREAM 数据。 |
在 varbinary(max) 列上指定 FILESTREAM 属性可使 SQL Server 将数据存储在本地 NTFS 文件系统中,而不是存储在数据库文件中。 虽然数据是单独存储的,但您可以使用所支持的用于处理存储在数据库中的 varbinary(max) 数据的相同 Transact-SQL 语句。
SqlClient 对 FILESTREAM 的支持
适用于 SQL Server 的 .NET 数据提供程序 (System.Data.SqlClient) 支持使用在 System.Data.SqlTypes 命名空间中定义的 SqlFileStream 类来读写 FILESTREAM 数据。 SqlFileStream 继承自 System.IO.Stream 类,该类提供了用于读写数据流的方法。 从流读取数据可将数据从流传输到一个数据结构,例如一个字节数组。 写入操作可将数据从该数据结构传输到一个流。
创建 SQL Server 表
下列 Transact-SQL 语句将创建一个名为 employees 的表并插入一行数据。 启用 FILESTREAM 存储之后,您可以将此表与下面的代码示例结合使用。 本主题的最后提供了指向 SQL Server 2008 联机丛书中的资源的链接。
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 读取数据。 示例代码获取文件的逻辑路径,并将 FileAccess 设置为 Read,而将 FileOptions 设置为 SequentialScan。 然后,示例代码将字节从 SqlFileStream 读入到缓存区中, 最后将这些字节写入到控制台窗口。
using (SqlConnection connection = new SqlConnection(
connStringBuilder.ToString()))
{
connection.Open();
SqlCommand command = new SqlCommand("", connection);
SqlTransaction tran = connection.BeginTransaction(
System.Data.IsolationLevel.ReadCommitted);
command.Transaction = tran;
command.CommandText =
"select Top(1) Photo.PathName(), "
+ "GET_FILESTREAM_TRANSACTION_CONTEXT () from employees";
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
FileStream fileStream = new SqlFileStream(path,
(byte[])reader.GetValue(1),
FileAccess.Read,
FileOptions.SequentialScan, 0);
// Read the contents as bytes and write them to the console
for (long index = 0; index < fileStream.Length; index++)
{
Console.Write(fileStream.ReadByte());
}
fileStream.Close();
}
}
tran.Commit();
}
覆盖 FILESTREAM 数据示例
下面的代码段演示如何将数据写入到 FILESTREAM(其中现有的所有数据将被覆盖)。 示例代码获取文件的逻辑路径,然后创建 SqlFileStream,并将 FileAccess 设置为 Write,而将 FileOptions 设置为 SequentialScan。 将一个单字节写入到 SqlFileStream,从而替换文件中的任何数据。
using (SqlConnection connection = new SqlConnection(
connStringBuilder.ToString()))
{
connection.Open();
SqlCommand command = new SqlCommand("", connection);
command.CommandText = "select Top(1) Photo.PathName(), "
+ "GET_FILESTREAM_TRANSACTION_CONTEXT () from employees";
SqlTransaction tran = connection.BeginTransaction(
System.Data.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
FileStream fileStream = new SqlFileStream(path,
(byte[])reader.GetValue(1),
FileAccess.Write,
FileOptions.SequentialScan, 0);
// Write a single byte to the file. This will
// replace any data in the file.
fileStream.WriteByte(0x01);
fileStream.Close();
}
}
tran.Commit();
}
插入 FILESTREAM 数据示例
下面的示例演示如何通过使用 Seek 方法将数据附加到 FILESTREAM 文件的结尾,以将数据写入到其中。 示例代码获取文件的逻辑路径,然后创建 SqlFileStream,并将 FileAccess 设置为 ReadWrite,而将 FileOptions 设置为 SequentialScan。 示例代码使用 Seek 方法找到文件结尾,并将一个单字节追加到现有的文件中。
using (SqlConnection connection = new SqlConnection(
connStringBuilder.ToString()))
{
connection.Open();
SqlCommand command = new SqlCommand("", connection);
command.CommandText = "select Top(1) Photo.PathName(), "
+ "GET_FILESTREAM_TRANSACTION_CONTEXT () from employees";
SqlTransaction tran = connection.BeginTransaction(
System.Data.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;
FileStream fileStream = new SqlFileStream(path,
(byte[])reader.GetValue(1),
FileAccess.ReadWrite,
FileOptions.SequentialScan, 0);
// Seek to the end of the file
fs.Seek(0, SeekOrigin.End);
// Append a single byte
fileStream.WriteByte(0x01);
fileStream.Close();
}
}
tran.Commit();
}
SQL Server 联机丛书中的资源
FILESTREAM 的完整文档位于 SQL Server 2008 联机丛书中的以下各节中。
主题 |
说明 |
---|---|
Designing and Implementing FILESTREAM Storage(设计和实现 FILESTREAM 存储) |
提供指向 FILESTREAM 文档和相关主题的链接。 |
介绍何时使用 FILESTREAM 存储以及该存储如何将 SQL Server 数据库引擎与 NTFS 文件系统集成。 |
|
介绍如何在 SQL Server 的实例上启用 FILESTREAM,如何创建数据库和表以存储 FILESTREAM 数据以及如何操作包含 FILESTREAM 数据的行。 |
|
Using FILESTREAM Storage in Client Applications(在客户端应用程序中使用 FILESTREAM 存储) |
介绍用于处理 FILESTREAM 数据的 Win32 API 函数。 |
FILESTREAM and Other SQL Server Features(FILESTREAM 与其他 SQL Server 功能) |
提供将 FILESTREAM 数据与 SQL Server 的其他功能一起使用时的注意事项、准则和限制。 |