方法文档:如何通过匿名 PL/SQL 块读取 BLOB 数据并将其写入数据库表
日期:2004 年 10 月 18 日
目标
在阅读此方法文档后,您应该能够:
-
使用 ODP.NET 执行一个匿名 PL/SQL 块
-
将图像数据从文件保存到数据库
- 将图像数据从数据库写入文件
前提
假设读者熟悉 MS Visual Studio.NET,并了解 ODP.NET 和数据库的基础知识。
简介
本文档说明如何使用匿名 PL/SQL 块将文件中的 BLOB(二进制大对象)数据插入数据库表中,然后从数据库中检索同一数据并将其写入文件。匿名 PL/SQL 块是一个的未命名 PL/SQL 语句块。此块在数据库中并不作为对象存储,而是一旦执行之后随即删除。
在此方法文档中,创建一个匿名 PL/SQL 块,将 BLOB 数据从图像文件插入数据库表,然后检索插入的图像并将其写到本地文件系统的另一个文件中。用户必须提供源图像文件的位置及目标图像文件的位置。OracleDbType.Blob 类型的参数被绑定到匿名 PL/SQL 块中。注意:要测试此方法文档程序,可使用任何类型的图像文件,如 .jpg、.gif 等。本方法文档程序未附带任何图像文件。
价值定位
使用匿名 PL/SQL 块的主要优点是提高了性能 — 它们可以用来在单个回程中批量执行一系列的 SQL 调用。该特性允许依次执行以分号分隔的多条命令。此外,这批 SQL 语句可以包含许多 SELECT 或非 SELECT 语句;如果包含了多条 SELECT 语句,那么将返回多个结果集。
匿名 Pl/SQL 块可用于检索 LOB。通过在 OracleCommand 中设置多个命令(每个命令对应数据集中的一个表),它们还可以用多个表填充一个数据集。在这种情况下,您可以从一个 PL/SQL 匿名块中返回多个 REF 游标,例如:
BEGIN OPEN :1 FOR SELECT * FROM A; OPEN :2 FOR SELECT * FROM B; OPEN :3 FOR SELECT * FROM C; END;
需要
创建数据库对象
本方法文档使用 TestBlob 表。使用 SQL*Plus 以任意用户身份(如 scott/tiger)连接到数据库,并运行清单 1 中给出的以下命令,创建所需的数据库对象。
清单 1
DROP TABLE TestBlob;
CREATE TABLE TestBlob (id number, photo BLOB);
|
|
代码预演
包括所需命名空间:在 .cs 或 .vb 文件中的“general declarations”部分中添加对命名空间的引用非常值得,这样可避免以后在脚本中限定其使用:
| C# |
using System;
using System.Data;
using Oracle.DataAccess.Client;
using Oracle.DataAccess.Types;
using System.IO;
using System.Text;
|
| Visual Basic .NET |
Imports System
Imports System.Data
Imports Oracle.DataAccess.Client
Imports Oracle.DataAccess.Types
Imports System.IO
Imports System.Text
|
1. 使用 ODP.NET 建立到 Oracle 数据库的连接:
| C# |
|
//Step 1
// Connect to database
// Note:Modify User Id, Password, Data Source as per your database setup
string constr = "User Id=Scott;Password=tiger;Data Source=orcl9i";
OracleConnection con = new OracleConnection(constr);
con.Open();
Console.WriteLine("Connected to database!");
|
| Visual Basic .NET |
'Step 1
' Connect to database
' Note:Modify User Id, Password, Data Source as per your database setup
Dim constr As String = "User Id=Scott;Password=tiger;Data Source=orcl9i"
Dim con As OracleConnection = New OracleConnection(constr)
con.Open()
Console.WriteLine("Connected to database!")
|
2. 将某个图像文件从源位置读入一个字节数组中:
| C# |
// Step 2
// Note:Modify the Source and Destination location
// of the image as per your machine settings
String SourceLoc = "D:/Images/photo.jpg";
String DestinationLoc = "D:/Images/TestImage.jpg";
// provide read access to the file
FileStream fs = new FileStream(SourceLoc, FileMode.Open,FileAccess.Read);
// Create a byte array of file stream length
byte[] ImageData = new byte[fs.Length];
//Read block of bytes from stream into the byte array
fs.Read(ImageData,0,System.Convert.ToInt32(fs.Length));
//Close the File Stream
fs.Close();
|
| Visual Basic .NET |
' Step 2
' Note:Modify the Source and Destination location
' of the image as per your machine settings
Dim SourceLoc As String = "D:/Images/photo.jpg"
Dim DestinationLoc As String = "D:/Images/TestImage.jpg"
' provide read access to the file
Dim Fs As FileStream = New FileStream(SourceLoc,
FileMode.Open, FileAccess.Read)
' Create a byte array of file stream length
Dim ImageData As Byte()
ReDim imagedata(fs.Length)
'Read block of bytes from stream into the byte array
fs.Read(ImageData, 0, System.Convert.ToInt32(fs.Length))
'Close the File Stream
fs.Close()
|
3. 使用 OracleCommand 对象创建一个匿名 PL/SQL 块:
| C# |
// Step 3
// Create Anonymous PL/SQL block string
String block = " BEGIN " +
" INSERT INTO testblob (id, photo) VALUES (100, :1); " +
" SELECT photo into :2 from testblob WHERE id = 100; " +
" END; ";
// Set command to create Anonymous PL/SQL Block
OracleCommand cmd = new OracleCommand();
cmd.CommandText = block;
cmd.Connection = con;
// Since executing an anonymous PL/SQL block, setting the command type
// as Text instead of StoredProcedure
cmd.CommandType = CommandType.Text;
|
| Visual Basic .NET |
' Step 3
' Create Anonymous PL/SQL block string
Dim block As String =
" BEGIN " & _
" INSERT INTO testblob (id, photo) VALUES (100, :1) ;" & _
" SELECT photo into :2 from testblob WHERE id = 100 ;" & _
" end ;"
' Set command to create Anonymous PL/SQL Block
Dim cmd As OracleCommand = New OracleCommand()
cmd.CommandText = block
cmd.Connection = con
' Since executing an anonymous PL/SQL block, setting the command type
' as Text instead of StoredProcedure
cmd.CommandType = CommandType.Text
|
4. 将包含图像数据的字节数组绑定到一个 OracleCommand 对象:
| C# |
// Step 4
// Setting Oracle parameters
// Bind the parameter as OracleDbType.Blob to command for inserting image
OracleParameter param = cmd.Parameters.Add("blobtodb", OracleDbType.Blob);
param.Direction = ParameterDirection.Input;
// Assign Byte Array to Oracle Parameter
param.Value = ImageData;
// Bind the parameter as OracleDbType.Blob to command for retrieving the image
OracleParameter param2 = cmd.Parameters.Add("blobfromdb", OracleDbType.Blob);
param2.Direction = ParameterDirection.Output;
|
| Visual Basic .NET |
' Step 4
' Setting Oracle parameters
' Bind the parameter as OracleDbType.Blob
' to command for inserting image
Dim param As OracleParameter = cmd.Parameters.Add("blobtodb", OracleDbType.Blob)
param.Direction = ParameterDirection.Input
' Assign Byte Array to Oracle Parameter
param.Value = ImageData
' Bind the parameter as OracleDbType.Blob
' to command for retrieving the image
Dim param2 As OracleParameter = cmd.Parameters.Add("blobfromdb", OracleDbType.Blob)
param2.Direction = ParameterDirection.Output
|
5. 使用 OracleCommand 对象执行此匿名块:
| C# |
|
// Step 5
// Execute the Anonymous PL/SQL Block
// The anonymous PL/SQL block inserts the image to the
// database and then retrieves the images as an output parameter
cmd.ExecuteNonQuery();
Console.WriteLine("Image file inserted to database from " + SourceLoc);
|
| Visual Basic .NET |
' Step 5
' Execute the Anonymous PL/SQL Block
' The anonymous PL/SQL block inserts the image to the database and then retrieves
' the images as an output parameter
cmd.ExecuteNonQuery()
Console.WriteLine("Image file inserted to database from "+ SourceLoc)
|
6. 将从数据库中检索到的 OracleBlob 对象保存到如下的目标位置:
| C# |
|
// Step 6
// Save the retrieved image to the DestinationLoc in the file system
// Create a byte array
byte[] byteData = new byte[0];
// fetch the value of Oracle parameter into the byte array
byteData = (byte[])((OracleBlob)(cmd.Parameters[1].Value)).Value;
// get the length of the byte array
int ArraySize = new int();
ArraySize = byteData.GetUpperBound(0);
// Write the Blob data fetched from database to the filesystem at the
// destination location
FileStream fs1 = new FileStream(@DestinationLoc,
FileMode.OpenOrCreate, FileAccess.Write);
fs1.Write(byteData, 0,ArraySize);
fs1.Close();
Console.WriteLine("Image saved to " + DestinationLoc + " successfully !");
Console.WriteLine(" ");
Console.WriteLine("***********************************************************");
Console.WriteLine("Before running this application again, execute 'Listing 1' ");
Console.WriteLine("given in 'Create Database Objects' section in the How-to.");
Console.WriteLine("***********************************************************");
|
| Visual Basic .NET |
' Step 6
' Save the retrieved image to the DestinationLoc in the file system
' Create a byte array
Dim byteData As Byte()
Dim Paramvalue As OracleBlob
Paramvalue = cmd.Parameters(1).Value
' fetch the value of Oracle parameter into the byte array
byteData = CType((Paramvalue.Value), Byte())
' get the length of the byte array
Dim ArraySize As Integer = New Integer()
ArraySize = byteData.GetUpperBound(0)
' Write the Blob data fetched from database to the filesystem at
' the destination location
Dim fs1 As FileStream = New FileStream(DestinationLoc,
FileMode.OpenOrCreate, FileAccess.Write)
fs1.Write(byteData, 0, ArraySize)
fs1.Close()
Console.WriteLine("Image saved to " + DestinationLoc + " successfully !")
Console.WriteLine(" ")
Console.WriteLine("***********************************************************")
Console.WriteLine("Before running this application again, execute 'Listing 1' "
Console.WriteLine("given in 'Create Database Objects' section in the How-to.")
Console.WriteLine("***********************************************************")
|
设置并运行此方法文档程序
1. 打开 Visual Studio.NET。
2. 创建控制台应用程序项目:
| C# |
用 C# 创建一个控制台应用程序项目。默认情况下,将 Class1.cs 添加到项目中。 |
| Visual Basic .NET |
用 VB.NET 创建一个控制台应用程序项目。默认情况下,将 Module1.vb 添加到项目中。
|
3. 请确保您的项目包含对 System、Oracle.DataAccess 及 System.Data 命名空间的引用。如果这些引用不存在,则添加对这些命名空间的引用。
4. 复制代码:
| C# |
|
使用 Solution Explorer 打开 Class1.cs。有关为此方法文章用 C# 编写的代码的完整清单,请单击这里。复制此代码,覆盖 Class1.cs 的内容。
|
| Visual Basic .NET |
使用 Solution Explorer 打开 Module1.vb。有关为此方法文章用 VB.NET 编写的代码的完整清单,请单击这里。复制此代码,覆盖 Module1.vb 的内容。
|
5. 按照代码的步骤 1 中的数据库设置修改用户 Id、口令及数据源。
6. 按照代码的步骤 2 中的计算机设置修改 SourceLoc、DestinationLoc 变量。
7. 要编译并运行此应用程序,请按下 Ctrl+F5。这将如图 1.1 所示显示输出:
 图 1.1 – 输出的屏幕截图
8. 再次运行此应用程序之前,请先执行“创建数据库对象”部分给出的清单 1。
资源
请在 OTN 示例代码论坛中发表有关此方法文档的意见。
|