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的结果传入,然后就简单了。