支持与下载

软件下载 资料下载 知识库 问与答 在线技术支持 建议与反馈 移动客户端

SQL Server 2008 New Feature- Filestream


昨天SQL Server 2008发布了,很多用户目前还没有用上SQL 2005,产品真是太快了,看样子学习的步伐也要加快了。这2天看了看SQL 2008的新功能,发现和05的版本相比功能是增加了一些,但是没有什么本质上的区别,只不过对于某些特殊的应用场景有了很好的优化。其中在数据类型上提供了几个新的数据类型,这里我们就先聊聊Filestream。其实对于很多开发人员来说如何存储BLOB的数据一直就是一个麻烦的事情。原来可选方案只有2中,将BLOB保存在SQL Server中的Image或者Text数据类型中,2进制数据放到SQL的数据文件中;另外就是将数据放到文件系统上,然后将文件的地址保存在数据库中。这2中方法各有利弊。在文件系统中的2进制数据在管理上相对比较麻烦,因为要保证对于数据的修改必须在文件系统和数据库中同时完成,或者可以说需要在一个事务中完成,这里还要注意的就是文件系统可不支持Transaction,而且这些文件也无法收到保护,其他用户可能会误操作删除文件。保存在数据库中的主要问题是性能,因为所有对于这些BLOB字段的操作也会占用Cache,而且这些Cache其实很难复用,有些浪费了,另外在BLOB字段中的数据长度最大只能有2G。FileStream就可以解决这些问题,Let’s go. Do it.
首先我们先需要在数据库引擎上开启FileStream Access,默认是禁用的。在Feb的CTP中 BOL上有一个地方写错了,@enable_level=2,我查了一下这个值的范围在0-2,BOL上写的是3,需要更正。
sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
exec sp_filestream_configure@enable_level=2;
GO
RECONFIGURE;
GO
 
然后需要shutdown 数据库,重新启动服务
接下来就是创建数据库并指定Filestream的文件组,同时创建表。
create database FSPhoto
on
primary
(name=PhotoData,FILENAME='D:\Code\SQLDB\PHOTO.mdf'),
FileGroup FileStreamGroup1 Contains
Filestream(Name=PhotoFile,FILENAME='D:\Code\SQLDB\Photo')
log on(Name=PhotoLog,FILENAME='D:\Code\SQLDB\PHOTO.ldf')
go
use FSPhoto
go
create table Photos
(
ID uniqueidentifier RowGuidCol not null unique,
Name nvarchar(50) not null,
FS varbinary(max) filestream null
)
go
接下来我们就开始使用了。你可以先去相应的文件夹看看,系统会创建出一些目录和文件,里面的.hdr文件是个系统文件,不要使用工具将其打开。
在Insert的时候我们通常需要提供一个展位符,这样我们才能获取相应文件在系统中的句柄,这点和之前版本中的Textptr函数差不多。
declare @id uniqueidentifier
select @id=NEWID()
insert photos values(@id,'aaa.jpg',cast('' as varbinary(max)))
select @id
这里要注意的是’’和null是不一样的,null不会再文件系统中创建文件也就是在后面我们无法获取句柄,而’’是创建了空文件,文件是空的但是有句柄。
select FS.PathName() from Photos where id =@id
你就可以看到这个文件的路径。
因为这个路径是受到SQL Server保护的,我们有那个File类无法获取。所以需要使用一个函数
[DllImport("sqlncli10.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern SafeFileHandle OpenSqlFilestream(string FilestreamPath,
UInt32 DesiredAccess,
UInt32 OpenOptions,
byte[] FilestreamTransactionContext,
UInt32 FilestreamTransactionContextLength,
Int64 AllocationSize);
使用这个函数去访问文件。除了这个函数之外还有一个重要的语句
select GET_FILESTREAM_TRANSACTION_CONTEXT()
这个语句就是可以将OpenSqlFilestream函数的操作与SQL的操作绑定在一个transaction中。这样就可以了。剩下的操作就是用构造一个FileStream类然后在构造函数中将OpenSqlFilestream的结果传入,然后就简单了。