如何读取和写入文件和从 BLOB 列使用 ADO.NET 和 Visual C#.net 中分块

注意:这篇文章是由无人工介入的微软自动的机器翻译软件翻译完成。微软很高兴能同时提供给您由人工翻译的和由机器翻译的文章, 以使您能使用您的语言访问所有的知识库文章。然而由机器翻译的文章并不总是完美的。它可能存在词汇,语法或文法的问题,就像是一个外国人在说中文时总是可能犯这样的错误。虽然我们经常升级机器翻译软件以提高翻译质量,但是我们不保证机器翻译的正确度,也不对由于内容的误译或者客户对它的错误使用所引起的任何直接的, 或间接的可能的问题负责。

点击这里察看该文章的英文版: 317043
为这篇文章的一个 Microsoft Visual Basic.net 版本,请参阅 317034
为这篇文章的一个 Microsoft Visual c + +.net 版本,请参阅 317044
概要
本分步指南介绍了如何使用 Microsoft SQL Server READTEXT 和 UPDATETEXT 语句来读取和写入数据从一个数据库表中的 BLOB (LongVarBinary) 列。

由于网络限制的您可能不得不检索大 BLOB 文件中较小的块,然后段一起而不是检索整个 BLOB 的区块文件一次。但是,ADO.NET 数据提供程序没有 GetChunkAppendChunk 方法可用于数据访问对象 (DAO) 和 ActiveX 数据对象 (ADO) 记录集 对象。本文介绍在较小的块区中检索数据的不同方法。

注释
  • 本文包含示例的这两个 SqlClient 数据提供程序和 OLE DB.net 数据提供程序。除了与类名,唯一区别是连接字符串和 SQL 参数的声明。 要检索 READTEXT 和 UPDATETEXT 语句基本的方法是相同的。
  • 在罗斯文示例数据库不存在的类别表中测试记录。您必须使用服务器资源管理器或另一种工具添加的 类别名称 记录设置为 测试。使用下面的示例后,您可能希望从数据库中删除该记录。若要去该记录在 SQL 查询分析器中,键入以下命令,然后按 F5:
    use Northwinddelete from Categories where CategoryName = 'Test'					

建议的硬件、 软件、 网络基础结构、 技能和知识和所需的服务包,介绍了以下各项:
  • Microsoft Windows 2000 专业版、 Windows 2000 Server,Windows 2000 高级服务器,或 Microsoft Windows NT 4.0 服务器
  • Microsoft Visual Studio.net
  • Microsoft SQL Server 7.0 或更高版本
本文假定您熟悉 ADO.NET 基础知识和语法。

  1. 打开 SQL 查询分析器。
  2. 键入以下命令,然后按 f5 键以将默认的数据库更改为罗斯文:
    use Northwind
  3. 键入以下命令并按 f5 键以插入一条新记录中的罗斯文数据库类别表:
    Insert into categories(categoryname) values ('Test')
    注释 您只需要将此记录添加到类别表,如果您要使用此示例而不修改任何此表中的现有数据。
  4. 在 Visual Studio.net 中,创建新 Visual C#.net Windows 应用程序项目。
  5. 管理员将 Form1.cs 文件顶部添加以下两行代码就可将引用添加到您的项目 System.Data.SQLClientSystem.Data.OleDb
    using System.Data.SqlClient;using System.Data.OleDb;
  6. 向 Form1 中添加四个按钮。分别更改为 SQLBlob2FileOlDbBlob2FileFile2OleDbBlobFile2SqlBlob文本 属性按钮。
  7. 添加下面的字符串变量声明在 Form1 公共类:
    string destfilepath;string sourcefilepath;					
  8. 将以下代码粘贴到在窗体的 Load 事件:
    destfilepath = @"c:\mytest.bmp";sourcefilepath = @"c:\windows\coffee bean.bmp";					
  9. 为每个按钮的 Click 事件中调用过程:
    // Click event for the button labeled SqlBlob2File.SqlChunkBlob2File(destfilepath);// Click event for the button labeled OLDbBlob2File.OlDbChunkBlob2File(destfilepath);// Click event for the button labeled File2OleDbBlob.ChunkFile2OleDbBlob(sourcefilepath);//Click event for the button labeled File2SqlBlob.ChunkFile2SqlBlob(sourcefilepath);					
  10. 在 Form1 中粘贴以下四个功能:
    public void SqlChunkBlob2File(string DestFilePath){   try   {	int PictureCol  = 0;  // position of Picture column in DataReader	int BUFFER_LENGTH  = 32768; // chunk size	SqlConnection cn = new SqlConnection("Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Northwind;");				// Make sure Photo is non-NULL and return TEXTPTR to it.				SqlCommand cmdGetPointer = new SqlCommand("SELECT @Pointer=TEXTPTR(Picture), @Length=DataLength(Picture) FROM Categories WHERE CategoryName='Test'", cn);	SqlParameter PointerOutParam = cmdGetPointer.Parameters.Add("@Pointer", SqlDbType.VarBinary, 100);	PointerOutParam.Direction = ParameterDirection.Output;	SqlParameter LengthOutParam  = cmdGetPointer.Parameters.Add("@Length", SqlDbType.Int);	LengthOutParam.Direction = ParameterDirection.Output;	cn.Open();	cmdGetPointer.ExecuteNonQuery();	if(PointerOutParam.Value == null) 	{		cn.Close();		// Add code to handle NULL BLOB.		return;	}				// Set up READTEXT command, parameters, and open BinaryReader.				SqlCommand cmdReadBinary = new SqlCommand("READTEXT Categories.Picture @Pointer @Offset @Size HOLDLOCK", cn);	SqlParameter PointerParam  = cmdReadBinary.Parameters.Add("@Pointer", SqlDbType.Binary, 16);	SqlParameter OffsetParam  = cmdReadBinary.Parameters.Add("@Offset", SqlDbType.Int);	SqlParameter SizeParam  = cmdReadBinary.Parameters.Add("@Size", SqlDbType.Int);	SqlDataReader dr; 	System.IO.FileStream fs = new System.IO.FileStream(DestFilePath, System.IO.FileMode.Create, System.IO.FileAccess.Write);	int Offset= 0;	OffsetParam.Value = Offset;	Byte []Buffer = new Byte[BUFFER_LENGTH ];				// Read buffer full of data and write to the file stream.				do	{		PointerParam.Value = PointerOutParam.Value;						// Calculate buffer size - may be less than BUFFER_LENGTH for last block.						if( (Offset + BUFFER_LENGTH) >= System.Convert.ToInt32(LengthOutParam.Value)) 			SizeParam.Value = System.Convert.ToInt32(LengthOutParam.Value) - Offset;		else SizeParam.Value = BUFFER_LENGTH;						dr = cmdReadBinary.ExecuteReader(CommandBehavior.SingleResult);		dr.Read();		dr.GetBytes(PictureCol, 0, Buffer, 0, System.Convert.ToInt32(SizeParam.Value));		dr.Close();		fs.Write(Buffer, 0, System.Convert.ToInt32(SizeParam.Value));		Offset += System.Convert.ToInt32(SizeParam.Value);		OffsetParam.Value = Offset;	}while(Offset < System.Convert.ToInt32(LengthOutParam.Value));	fs.Close();	cn.Close();   }   catch(SqlException ex)   {   MessageBox.Show (ex.Message);   }}public void OleDbChunkBlob2File(string DestFilePath){   try   {	int PictureCol= 0; // Position of picture column in DataReader.	int BUFFER_LENGTH = 32768;// Chunk size.	OleDbConnection cn = new OleDbConnection("Provider=SQLOLEDB;Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Northwind;");				// Make sure Photo is non-NULL and return TEXTPTR to it.			OleDbCommand cmdGetPointer = new OleDbCommand("SELECT ?=TEXTPTR(Picture), ?=DataLength(Picture) FROM Categories WHERE CategoryName='Test'", cn);	OleDbParameter PointerOutParam =  cmdGetPointer.Parameters.Add("@Pointer", OleDbType.VarBinary, 100);	PointerOutParam.Direction = ParameterDirection.Output;	OleDbParameter LengthOutParam = cmdGetPointer.Parameters.Add("@Length", OleDbType.Integer);	LengthOutParam.Direction = ParameterDirection.Output;	cn.Open();	cmdGetPointer.ExecuteNonQuery();if(PointerOutParam.Value == DBNull.Value )	{		cn.Close();		// Add code to deal with NULL BLOB.		return;	}				// Set up READTEXT command, parameters, and open BinaryReader.				OleDbCommand cmdReadBinary = new OleDbCommand("READTEXT Categories.Picture ? ? ? HOLDLOCK", cn);	OleDbParameter PointerParam  = cmdReadBinary.Parameters.Add("@Pointer", OleDbType.Binary, 16);	OleDbParameter OffsetParam  = cmdReadBinary.Parameters.Add("@Offset", OleDbType.Integer);	OleDbParameter SizeParam  = cmdReadBinary.Parameters.Add("@Size", OleDbType.Integer);	OleDbDataReader dr;	System.IO.FileStream fs = new System.IO.FileStream(DestFilePath, System.IO.FileMode.Create, System.IO.FileAccess.Write);	int Offset= 0;	OffsetParam.Value = Offset;	Byte[] Buffer = new Byte[BUFFER_LENGTH];				//Read buffer full of data and write to the file stream.				do	{		PointerParam.Value = PointerOutParam.Value;						// Calculate buffer size - may be less than BUFFER_LENGTH for last block.						if((Offset + BUFFER_LENGTH) >= System.Convert.ToInt32(LengthOutParam.Value))			SizeParam.Value = System.Convert.ToInt32(LengthOutParam.Value) - Offset;		else SizeParam.Value = BUFFER_LENGTH;						dr = cmdReadBinary.ExecuteReader(CommandBehavior.SingleResult);		dr.Read();		dr.GetBytes(PictureCol, 0, Buffer, 0, System.Convert.ToInt32(SizeParam.Value));		dr.Close();		fs.Write(Buffer, 0, System.Convert.ToInt32(SizeParam.Value));		Offset += System.Convert.ToInt32(SizeParam.Value);		OffsetParam.Value = Offset;	}while( Offset < System.Convert.ToInt32(LengthOutParam.Value));	fs.Close();	cn.Close();   }   catch(OleDbException ex)   {   MessageBox.Show (ex.Message);   }}				
  11. 按 f5 键运行该的代码,然后单击 $ File2OleDbBlob 以确保您在尝试写出到磁盘上的.bmp 文件之前加载 SQL Server 数据库中的图像。

以下函数使用 SQL Server READTEXT 语句和 DataReader 检索单行的、 单列的行集合中的 BLOB 值的一部分。使用两个命令: 第一个检索 BLOB 字段以及其位置的指针的大小 ; 第二个执行该 READTEXT 命令。READTEXT 命令检索的字节数组中的数据块,并增加偏移。字节数组写入到磁盘通过 在 System.IO.Filesream 对象。

以下函数使用的数据块从字节数组写入 BLOB 列 命令参数 对象和 $ SQL Server UPDATETEXT 语句。因此 TEXTPTR 检索前,为列指定的单字节 BLOB 列不能使用这种方法为 NULL。上 UPDATETEXT 语句在第一个执行 DeleteParam.Value 被设置为 1。这之前插入该文本块列中删除现有的字节,并防止出现外来数据追加到该 BLOB。UPDATETEXT 语句是执行多个时间每次调用后增加缓冲区的大小与偏移量。
private void ChunkFile2SqlBlob(string SourceFilePath){   try   {	int BUFFER_LENGTH = 32768; // Chunk size.	SqlConnection cn = new SqlConnection("Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Northwind;");				// Make sure Photo is non-NULL and return TEXTPTR to it.			SqlCommand cmdGetPointer = new SqlCommand("SET NOCOUNT ON;UPDATE Categories SET Picture = 0x0 WHERE CategoryName='Test';" +					"SELECT @Pointer=TEXTPTR(Picture) FROM Categories WHERE CategoryName='Test'", cn);	SqlParameter PointerOutParam  = cmdGetPointer.Parameters.Add("@Pointer", SqlDbType.VarBinary, 100);	PointerOutParam.Direction = ParameterDirection.Output;	cn.Open();	cmdGetPointer.ExecuteNonQuery();			// Set up UPDATETEXT command, parameters, and open BinaryReader.				SqlCommand cmdUploadBinary = new SqlCommand("UPDATETEXT Categories.Picture @Pointer @Offset @Delete WITH LOG @Bytes", cn);	SqlParameter PointerParam  = cmdUploadBinary.Parameters.Add("@Pointer", SqlDbType.Binary, 16);	SqlParameter OffsetParam= cmdUploadBinary.Parameters.Add("@Offset", SqlDbType.Int);	SqlParameter DeleteParam = cmdUploadBinary.Parameters.Add("@Delete", SqlDbType.Int);	DeleteParam.Value = 1;  // delete 0x0 character				SqlParameter BytesParam  = cmdUploadBinary.Parameters.Add("@Bytes", SqlDbType.Binary, BUFFER_LENGTH);	System.IO.FileStream fs = new System.IO.FileStream(SourceFilePath, System.IO.FileMode.Open, System.IO.FileAccess.Read);	System.IO.BinaryReader br = new System.IO.BinaryReader(fs);	int Offset = 0;	OffsetParam.Value = Offset;				// Read buffer full of data and execute UPDATETEXT statement.				Byte [] Buffer = br.ReadBytes(BUFFER_LENGTH);	while(Buffer.Length > 0)	{		PointerParam.Value = PointerOutParam.Value;		BytesParam.Value = Buffer;		cmdUploadBinary.ExecuteNonQuery();		DeleteParam.Value = 0; //Do not delete any other data.		Offset += Buffer.Length;		OffsetParam.Value = Offset;		Buffer = br.ReadBytes(BUFFER_LENGTH);	}	br.Close();	fs.Close();	cn.Close();   }   catch(SqlException ex)   {   MessageBox.Show (ex.Message);   }			}public void ChunkFile2OleDbBlob(string SourceFilePath){   try   {	         int BUFFER_LENGTH = 32768; // chunk size	OleDbConnection cn = new OleDbConnection("Provider=SQLOLEDB;Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Northwind;");			// Make sure Photo is non-NULL and return TEXTPTR to it.			OleDbCommand cmdGetPointer = new OleDbCommand("SET NOCOUNT ON;UPDATE Categories SET Picture = 0x0 WHERE CategoryName='Test';" +				"SELECT ?=TEXTPTR(Picture) FROM Categories WHERE CategoryName='Test'", cn);	OleDbParameter PointerOutParam = cmdGetPointer.Parameters.Add("@Pointer", OleDbType.VarBinary, 100);	PointerOutParam.Direction = ParameterDirection.Output;	cn.Open();	cmdGetPointer.ExecuteNonQuery();				// Set up UPDATETEXT command, parameters, and open BinaryReader.				OleDbCommand cmdUploadBinary = new OleDbCommand("UPDATETEXT Categories.Picture ? ? ? WITH LOG ?", cn);	OleDbParameter PointerParam = cmdUploadBinary.Parameters.Add("@Pointer", OleDbType.Binary, 16);	OleDbParameter OffsetParam = cmdUploadBinary.Parameters.Add("@Offset", OleDbType.Integer);	OleDbParameter DeleteParam   = cmdUploadBinary.Parameters.Add("@Delete", OleDbType.Integer);	DeleteParam.Value = 1;  // delete 0x0 character	OleDbParameter BytesParam = cmdUploadBinary.Parameters.Add("@Bytes", OleDbType.Binary, BUFFER_LENGTH);	System.IO.FileStream fs = new System.IO.FileStream(SourceFilePath, System.IO.FileMode.Open, System.IO.FileAccess.Read);	System.IO.BinaryReader br = new System.IO.BinaryReader(fs);	int Offset= 0;	OffsetParam.Value = Offset;				// Read buffer full of data and execute UPDATETEXT statement.			         Byte[] Buffer = br.ReadBytes(BUFFER_LENGTH);	while(Buffer.Length > 0)	{		PointerParam.Value = PointerOutParam.Value;		BytesParam.Value = Buffer;		cmdUploadBinary.ExecuteNonQuery();		DeleteParam.Value = 0;// Do not delete any other data.		Offset += Buffer.Length;		OffsetParam.Value = Offset;		Buffer = br.ReadBytes(BUFFER_LENGTH);	}	br.Close();	fs.Close();	cn.Close();		   }   catch(OleDbException ex)   {   MessageBox.Show (ex.Message);   }}				
笔记
  • 本文中介绍的代码可能不是适合于对 LongVarChar 或 LongVarWChar 而无需进行修改的列的使用。
  • 您必须修改连接字符串和对应于您自己的服务器的 SQL 语句。您还必须添加错误检查,如果您的查询不返回任何记录。
  • READTEXT 和 $ UPDATETEXT 是特定于 Microsoft SQL Server。不同的数据库系统可能有类似,您可以使用该命令。
参考
有关如何读取和写入数据,而不分块的其他信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
316887如何读取和写入文件和从 BLOB 列使用 ADO.NET 和 Visual Basic.net
317017如何读取和写入文件和从 BLOB 列使用 ADO.NET 和 Visual c + +.net
317016如何读取和写入文件或从 BLOB 列使用 ADO.NET 和 Visual C#.net
有关如何使用 ADO.NET 中的 blob 的详细信息请访问下面的 Microsoft 开发人员网络 (MSDN) 的网站:
kbblob kbnetsearch kbchunking

警告:本文已自动翻译

属性

文章 ID:317043 - 上次审阅时间:10/27/2004 18:23:41 - 修订版本: 3.3

Microsoft ADO.NET (included with the .NET Framework), Microsoft ADO.NET 1.1, Microsoft Visual C# .NET 2002 标准版, Microsoft Visual C# .NET 2003 标准版

  • kbmt kbsystemdata kbsqlclient kbhowtomaster KB317043 KbMtzh
反馈