如何读取和写入文件和从 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 Northwind
    delete from Categories where CategoryName = 'Test'
    					

Requirements

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

Create a project and add code

  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 数据库中的图像。

Read chunks from a BLOB column

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

Write chunks to a BLOB column

以下函数使用的数据块从字节数组写入 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) 的网站:
从数据库获取 BLOB 值
http://msdn.microsoft.com/en-us/library/87z0hy49.aspx

属性

文章编号: 317043 - 最后修改: 2004年10月27日 - 修订: 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
机器翻译
注意:这篇文章是由无人工介入的微软自动的机器翻译软件翻译完成。微软很高兴能同时提供给您由人工翻译的和由机器翻译的文章, 以使您能使用您的语言访问所有的知识库文章。然而由机器翻译的文章并不总是完美的。它可能存在词汇,语法或文法的问题,就像是一个外国人在说中文时总是可能犯这样的错误。虽然我们经常升级机器翻译软件以提高翻译质量,但是我们不保证机器翻译的正确度,也不对由于内容的误译或者客户对它的错误使用所引起的任何直接的, 或间接的可能的问题负责。
点击这里察看该文章的英文版: 317043
Microsoft和/或其各供应商对于为任何目的而在本服务器上发布的文件及有关图形所含信息的适用性,不作任何声明。 所有该等文件及有关图形均"依样"提供,而不带任何性质的保证。Microsoft和/或其各供应商特此声明,对所有与该等信息有关的保证和条件不负任何责任,该等保证和条件包括关于适销性、符合特定用途、所有权和非侵权的所有默示保证和条件。在任何情况下,在由于使用或运行本服务器上的信息所引起的或与该等使用或运行有关的诉讼中,Microsoft和/或其各供应商就因丧失使用、数据或利润所导致的任何特别的、间接的、衍生性的损害或任何因使用而丧失所导致的之损害、数据或利润不负任何责任。

提供反馈

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com