一、引言
在構建數據驅動的應用程序時,經常需要捕獲文本和二進制數據。這樣的程 序可能需要存儲圖像,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看上去如http://www.yourserver.com/ShowImage.aspx? ID=4352的形式,而如果該圖像直接存儲在文件系統中,URL將更為直接些-例如 http://www.yourserver.com/UploadedImages/Sam.jpg。
·為顯示圖像提供更好的工具支持-如果你在使用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列則存儲了 該圖片實際的二進制內容。