使用 ASP.NET 2.0 在 SQL Server 2000 和 2005 中将对象作为 BLOB 存储和检索






4.34/5 (16投票s)
操作指南:通过 ASP.NET 2.0 使用 ADO.NET 读取和写入 BLOB 数据。
引言
在某些情况下,我们的应用程序必须存储文档,比如文档管理系统。我看到在 Web 或 Windows 应用程序中处理图像/文件的两个主要选项是将图像作为 BLOB 存储在数据库中,或者将文件的URL/UNC存储在数据库中,然后将图像文件实际存储在文件共享上。
背景
在 SQL Server 中存储 BLOB 对象在检索时确实很麻烦。因此,最常用的网站图像管理方式不是将图像存储在数据库中,而只是将 URL 存储在数据库中,并将图像存储在已成为 Web 服务器虚拟文件夹的文件共享上。
将 BLOB 值写入数据库
您可以将二进制大对象(BLOB)作为二进制数据或字符数据写入数据库,具体取决于数据源中字段的类型。 要将 BLOB 值写入数据库,请发出适当的 INSERT
或 UPDATE
语句,并将 BLOB 值作为输入参数传递。 如果您的 BLOB 存储为文本,例如 SQL Server 文本字段,您可以将 BLOB 作为字符串参数传递。 如果 BLOB 以二进制格式存储,例如 SQL Server 图像字段,您可以传递类型为 byte
的数组作为二进制参数。
首先要注意的是,blob 数据不是内联存储的,也就是说,它与其余数据不在同一页上(除非特别指示:请参阅sp_tableoption)。 其次,所有“blob”数据都可以强制放入单独的文件组中,您可以将该文件组放置在不同的 IO 子系统上。 blob 的最大大小为 2GB,多个 blob 可以共享 8K 页面,因此最小的“blob”大小将是您的最小文件。
在设计表以存储 BLOB 时,始终定义一个列来存储文件类型或内容类型,例如.doc、.xls等。 这对于从数据库中检索文件以识别内容类型非常重要。
表结构
用于存储 BLOB 的表
if exists (select * from dbo.sysobjects
where id = object_id(N'[dbo].[Docs]') and
OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[Docs]
GO
CREATE TABLE [dbo].[Docs] (
[docid] [int] IDENTITY (1, 1) NOT NULL ,
[docuid] [uniqueidentifier] NULL ,
[docname] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
[document] [image] NOT NULL ,
[doctype] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[Docs] WITH NOCHECK ADD
CONSTRAINT [PK_Docs] PRIMARY KEY CLUSTERED
(
[docid]
) ON [PRIMARY]
GO
存储过程
用于转储/检索 BLOB 的过程
CREATE proc sp_adddoc(@docname nvarchar(50), @document image, @doctype nvarchar(50))
as
begin
insert into Docs(docuid, docname, document, doctype)
valueS(newid(), @docname, @document, @doctype)
end
GO
CREATE proc sp_getdoc(@docuid uniqueidentifier)
as
begin
select document, docname, doctype from Docs where docuid = @docuid
end
GO
使用代码从 ASPX 将文档转储到数据库中
让我们尝试一个场景,假设我们需要将文档上传到具有主键 (PK) 的数据库中。
开始吧!将“FileUpload
”和“Button
”控件拖放到网页 (.aspx) 中,并将下面的代码粘贴到“Upload”按钮的“Button_Click
”事件中。 在尝试此代码段之前,不要忘记在“Web.config”文件中提及连接字符串。
protected void btnUpload_Click(object sender, EventArgs e)
{
//Validation to make sure that the file
//upload control has a valid file
if (!FileUpload1.HasFile) return;
//Get the binary array directly from the control
byte[] binary = new byte[FileUpload1.PostedFile.ContentLength];
binary = FileUpload1.FileBytes;
//SQL connection and paramters to dump
//the document via stored procedure
SqlParameter param = null;
SqlConnection conn = new SqlConnection(
ConfigurationManager.ConnectionStrings["menu"].ToString());
SqlCommand cmd = new SqlCommand("sp_adddoc", conn);
cmd.CommandType = CommandType.StoredProcedure;
//Parameters and values
param = new SqlParameter("@docname", SqlDbType.NVarChar, 50,
ParameterDirection.Input, false, 0, 0, "",
DataRowVersion.Default, FileUpload1.FileName);
cmd.Parameters.Add(param);
param = new SqlParameter("@document", SqlDbType.Image);
param.Direction = ParameterDirection.Input;
param.Value = binary;
cmd.Parameters.Add(param);
param = new SqlParameter("doctype", SqlDbType.NVarChar, 50,
ParameterDirection.Input, false, 0, 0, "",
DataRowVersion.Default, FileUpload1.PostedFile.ContentType);
cmd.Parameters.Add(param);
//Connection open and execute
conn.Open();
cmd.ExecuteNonQuery();
}
使用代码从 ASPX 检索文件
现在,是时候检索 BLOB 并将其呈现到网页了。 要检索文档,我们必须提供项目的 PK。 使用下面的代码片段从数据库中取回 BLOB。 在这里,我使用“二进制流式传输”以获得更好的 IO 性能。
private void WriteDocumentWithStreaming()
{
// Request.QueryString["docid"].ToString();
string docuid = "864d9871-b6f2-41ec-8a4d-615bd0f03763";
//Connection and Parameters
SqlParameter param = null;
SqlConnection conn = new SqlConnection(
ConfigurationManager.ConnectionStrings["menu"].ToString());
SqlCommand cmd = new SqlCommand("sp_getdoc", conn);
cmd.CommandType = CommandType.StoredProcedure;
param = new SqlParameter("@docuid", SqlDbType.NVarChar, 100);
param.Direction = ParameterDirection.Input;
param.Value = docuid;
cmd.Parameters.Add(param);
//Open connection and fetch the data with reader
conn.Open();
SqlDataReader reader =
cmd.ExecuteReader(CommandBehavior.CloseConnection);
if (reader.HasRows)
{
reader.Read();
//
string doctype = reader["doctype"].ToString();
string docname = reader["docname"].ToString();
//
Response.Buffer = false;
Response.ClearHeaders();
Response.ContentType = doctype;
Response.AddHeader("Content-Disposition",
"attachment; filename=" + docname);
//
//Code for streaming the object while writing
const int ChunkSize = 1024;
byte[] buffer = new byte[ChunkSize];
byte[] binary = (reader["document"]) as byte[];
MemoryStream ms = new MemoryStream(binary);
int SizeToWrite = ChunkSize;
for (int i = 0; i < binary.GetUpperBound(0)-1; i=i+ChunkSize)
{
if (!Response.IsClientConnected) return;
if (i + ChunkSize >= binary.Length)
SizeToWrite = binary.Length - i;
byte[] chunk = new byte[SizeToWrite];
ms.Read(chunk, 0, SizeToWrite);
Response.BinaryWrite(chunk);
Response.Flush();
}
Response.Close();
}
}
如何在 WinForms 中处理 BLOB?
请参阅我的文章这里。
如果我收到足够多的关于这个的查询,我将开始撰写更多文章。我的博客。