SQL Server 2008中的FileStream支持
服务器有一个属性,即指定该服务器是怎么支持文件流的
/*
实际上文件流的出现就是为了解决对大对象的存储中一个矛盾。
对于大对象,第一种方式是存储在数据库里面,这种方式一般使用image字段,或者varbinary(max)来做。好处是可以统一备份,但实际上读取效率比较低。大于1MB的文件就会有问题
第二种方式是文件存储在文件系统,而数据库中存储了一个路径。这种方式数据库压力减轻了,却很不方便统一备份和管理。
SQL SERVER 2008的文件流其实就是二者的统一。文件还是放在文件系统的,但由数据库进行管理。可以统一备份和还原。
FILESTREAM不是一个字段类型,它定义在字段后面,声明该列用于文件流即可。该列依然是用二进制保存的
一般都是在数据库中要特别添加一个文件组和一个或多个文件用来存储FileStream的数据的。
然后,在磁盘上面有一个目录(Test),里面会有一个filestream.hdr文件
客户端是透明的。无需要什么修改。
*/
--这段代码的作用是启用服务器支持文件流
EXEC sp_filestream_configure
@enable_level = 3;
CREATE DATABASE Archive
ON
PRIMARY ( NAME = Arch1,
FILENAME = 'c:\lab\archdat1.mdf'),
FILEGROUP FileStreamGroup1 CONTAINS FILESTREAM( NAME = Arch3,
FILENAME = 'c:\lab\filestream1')
LOG ON ( NAME = Archlog1,
FILENAME = 'c:\lab\archlog1.ldf')
GO
CREATE TABLE Archive.dbo.Records
(
[Id] [uniqueidentifier] ROWGUIDCOL NOT NULL UNIQUE,
[SerialNumber] INTEGER UNIQUE,
[Chart] VARBINARY(MAX) FILESTREAM NULL --这一句指示该列要用文件流存储
--这里还可以做一些改进,就是加入文件类型的一个字段(FileName)
)
FILESTREAM_ON FileStreamGroup1 --该行指示存储到哪一个文件流文件组
GO
--下面代码无法运行,如果一个表要使用文件流,则必须有一个GUID列,而且作为唯一键列
CREATE TABLE Archive.dbo.Records2
(
--[Id] [uniqueidentifier] ROWGUIDCOL NOT NULL UNIQUE,
[SerialNumber] INTEGER UNIQUE,
[Chart] VARBINARY(MAX) FILESTREAM NULL --这一句指示该列要用文件流存储
)
FILESTREAM_ON FileStreamGroup1 --该行指示存储到哪一个文件流
GO
INSERT INTO Archive.dbo.Records
VALUES (newid (), 1, NULL);
GO
INSERT INTO Archive.dbo.Records
VALUES (newid (), 2,
CAST ('' as varbinary(max)));
GO
INSERT INTO Archive.dbo.Records
VALUES (newid (), 3,
CAST ('Seismic Data' as varbinary(max)));
GO
UPDATE Archive.dbo.Records
SET [Chart] = CAST('Xray 1' as varbinary(max))
WHERE [SerialNumber] = 2;
DELETE Archive.dbo.Records
WHERE SerialNumber = 1;
GO
SELECT * FROM Archive.dbo.Records
GO
对于客户端编程来说,是没有区别的,这只是服务器的一个存储改变
保存
//保存音乐文件
try
{
OpenFileDialog dialog = new OpenFileDialog();
dialog.Filter = "音乐文件(*.mp3)|*.mp3";
if (dialog.ShowDialog() == DialogResult.OK)
{
using (SqlConnection conn = new SqlConnection(CONNECTIONSTRING)) {
conn.Open();
using (SqlCommand cmd = conn.CreateCommand()) {
cmd.CommandText = "INSERT INTO BINARYTABLE(BINARYCONTENTS) VALUES(@file)";
FileStream fs = new FileStream(dialog.FileName, FileMode.Open);
byte[] bytes = new byte[fs.Length];
fs.Read(bytes, 0, bytes.Length);
SqlParameter param = new SqlParameter("@file", SqlDbType.VarBinary,1000000);
param.Value = bytes;
cmd.Parameters.Add(param);
MessageBox.Show(cmd.ExecuteNonQuery() == 1 ? "成功保存文件" : "保存文件失败");
fs.Close();
}
conn.Close();
}
}
else
MessageBox.Show("用户取消了操作");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
读取
//读取音乐文件
try
{
using (SqlConnection conn = new SqlConnection(CONNECTIONSTRING)) {
conn.Open();
using (SqlCommand cmd = conn.CreateCommand()) {
cmd.CommandText = "select top 1 BinaryContents from BinaryTable order by ID desc";
SqlDataReader reader = cmd.ExecuteReader();
SaveFileDialog dialog = new SaveFileDialog();
dialog.Filter = "音乐文件(*.mp3)|*.mp3";
if (dialog.ShowDialog() == DialogResult.OK)
{
reader.Read();
System.Data.SqlTypes.SqlBinary result = reader.GetSqlBinary(0);//值得注意的是这里并没有什么GetSqlImage的方法
FileStream fs = new FileStream(dialog.FileName, FileMode.Create);
fs.Write(result.Value, 0, result.Length);
fs.Close();
reader.Close();
}
else
MessageBox.Show("用户取消操作");
}
conn.Close();
}
}
catch (Exception ex) { MessageBox.Show(ex.Message); }