一、 引言
在构建数据驱动的应用程序时,经常需要捕获文本和二进制数据。这样的程序可能需要存储图像,PDF,Word文件或其它二进制数据。能够使用两种方式来存储这些二进制数据:存储在web服务器的文件系统上并添加一个对数据库中相应文件的引用;或直接存储在数据库本身。
文本数据,例如字符串,数字,日期,GUID,货币值,等等-在数据库系统中都有适当的和相应的数据类型定义。例如,在Microsoft SQL Server中,你可以使用int数据类型来存储一个整数值;而为了存储一个字符串值,你可以使用一个varchar或nvarchar类型。另外,数据库还提供了用于存储二进制数据的类型定义。在Microsoft SQL SERVER 2000及早期版本中,使用image数据类型来存储二进制数据;而在SQL SERVER 2005中,使用varbinary(MAX)数据类型。使用上面两种方式中的任何一种,这些数据类型都能够存储可达2GB大小的二进制数据。
不过,当直接把二进制数据存储在数据库时,需要增加一些额外工作来实现插入、更新和检索二进制数据。幸好,我们可以通过更高级的数据存取库-例如ADO.NET-对这种复杂的低级T-SQL操作加以抽象,从而使问题变得相当简单。然而,通过ADO.NET方式使用二进制数据与使用文本数据的确有点不同。在本文中,我们将分析如何使用ADO.NET和ASP.NET 2.0 SqlDataSource控件直接通过一个数据库来存储和检索图像文件。请接着往下阅读!
二、 把数据存储在数据库中与存储在文件系统中的比较
正如刚才介绍的,当捕获一个应用程序中的二进制数据时,该二进制数据既可以直接存储在数据库中也可以作为一个文件保存在web服务器的文件系统中-仅保持一个对数据库中文件的引用。根据我的体验,我发现大多数开发者更喜欢在文件系统中存储二进制数据,这主要基于下列原因:
· 需要较少的工作-存储和检索存储在数据库中的二进制需要更多的编码工作。而且,更新这些二进制数据也会更为容易-不需要与数据库通讯,只须直接修改文件即可!
· 指向文件的URL更为直接-正如我们将在本文中所看到的,为了提供存取存储在一个数据库中的二进制数据,我们需要创建另一个能够返回该数据的ASP.NET页面。典型地,会把相应于数据库中对应记录(返回它的二进制数据)的一个唯一的标识符传递给这个页面。结果是,为了存取该二进制数据-比方说一个上传的图像-该URL看上去如?ID=4352的形式,而如果该图像直接存储在文件系统中,URL将更为直接些-例如。
· 为显示图像提供更好的工具支持-如果你在使用ASP.NET 2.0,那么,你可以在GridView或DetailsView控件中使用ImageField控件来显示一个图像(它的图像路径存储在数据库中)。然而,遗憾的是,这个ImageField却无法直接显示数据库中的图像数据(既然它要求查询一个外部页面并且返回相应的数据)。
· 性能-既然二进制文件存储在web服务器的文件系统而不是存储在数据库中,那么,应用程序可以访问数据库中较少的数据,从而减少了对数据库的要求,也相应地减少了存在于web和数据库服务器之间的网络拥挤。
把数据直接存储在数据库的主要优点在于,它能够使数据成为"自包含的"。既然所有的数据都包含在数据库中,那么,数据支持、数据在数据库服务器间的移动以及数据库复制等等就容易得多了,因为不存在担心复制或备份存储在文件系统中的二进制内容这样的问题。
如往常一样,至于选择哪种存储方案要具体依赖于实际的使用场所和业务需要。例如,我开发过一个客户端,其中的二进制数据必须存储在数据库中,因为它们使用的报告软件仅能够在报告中包括二进制数据-如果它来自于数据库的话。在另一种情况下,我的一个同事在开发一个工程,其中的二进制文件需要为web应用程序使用并且可经由FTP使用,这种情况很有必要把二进制数据存储在文件系统中。
三、 创建一个存储二进制数据的数据库表格
本文中的其它部分将分析一个简单的ASP.NET2.0图像画廊应用程序,我使用微软SQL Server 2005 Express Edition编写的,用于展示本文所阐述的直接从一个数据库中存储和检索二进制数据的相关概念。
这个图像画廊应用程序的数据模型包括一个表格-Pictures,其中的每一个记录对应画廊中的一幅图片。这个Pictures表格的MIMEType域中存储了上载图像(对于JPG文件是image/jpeg,对于GIF文件是image/gif,等等)的MIME类型;这里的MIME类型向浏览器指定如何生成该二进制数据。其中的ImageData列则存储了该图片实际的二进制内容。