在 .NET 中使用大对象

开发人员:.NET

在 .NET 中使用大对象
作者:Jason Price

了解如何使用 .NET 读写大对象 (LOB) 以及如何通过 BFILE 读取数据。

本文相关下载:
· 示例代码
· Oracle 数据库 10g
· ODP.NET(版本 10.1.0.2.0 或更高版本,如果需要的话)
· Microsoft .NET Framework 和 SDK

本文是上一篇介绍在 .NET 中使用数据库对象文章的后续文章。在本文中,您将了解如何在 Visual Basic .NET (VB.NET) 和 Visual C# .NET (C#) 中使用大对象。尤其是,您将了解如何使用 .NET 读写大对象 (LOB)。您还将了解如何通过 BFILE(可以将其看作是文件指针)读取数据。本文中引用的所有脚本和文件都可在这里找到。本文假定您大体上了解 C# 和 VB.NET 编程。

本文适用于开发人员,您应大体上了解 C# 和 VB.NET 编程并具有 LOB 基础知识。如果您需要 LOB 的介绍,可以阅读 Oracle LOB 文档,也可以阅读我编写的 Oracle 数据库 10g SQL(McGraw-Hill/Osborne,2004)一书。

所需软件

如果您要跟随我们逐步完成本文中给出的示例,那么您需要安装以下软件:

  • Windows NT 4.0、Windows 2000、Windows XP Professional 或 Windows Server 2003
  • 访问已安装好的 Oracle 数据库
  • Oracle 客户机(版本 10.1.0.2.0 或更高版本)
  • Oracle Net(版本 10.1.0.2.0 或更高版本)
  • Oracle Data Providers for .NET(版本 10.1.0.2.0 或更高版本,如果需要的话)
  • Microsoft .NET Framework(版本 1.0 或更高版本)
  • Microsoft .NET 框架 SDK(版本 1.0 或更高版本)

注意:如果您使用的是 Oracle 数据库 10g(Oracle8i 版本 3 8.1.7 或更高版本)之前的版本,则需要在数据库之外单独下载和安装 Oracle Data Provider for .NET (ODP.NET)。

ODP.NET 驱动程序针对 Oracle 数据库访问进行了优化,因此可以获得最佳性能,并且它们还支持 Oracle 数据库的丰富特性,如 BFILE、BLOB、CLOB、XMLType 等。如果您正在开发基于 Oracle 数据库的 .NET 应用程序,那么就特性和性能来讲,ODP.NET 无疑是最佳的选择。

注意:ODP.NET 驱动程序针对 Oracle 数据库访问进行了优化,因此可以获得最佳性能,并且它们还支持 Oracle 数据库的丰富特性,如 BFILE、BLOB、CLOB、XMLType 等。如果您正在开发基于 Oracle 数据库的 .NET 应用程序,那么就特性和性能来讲,ODP.NET 无疑是最佳的选择。

数据库模式设置

首先,您需要设置将包含本文所用表的数据库模式。您首先必须创建一个名为 lob_user 的用户,并按如下所示授予该用户所需权限。(您必须先以具有数据库管理员权限的用户身份登录数据库,才能创建用户和授予权限):

CREATE USER lob_user IDENTIFIED BY lob_password;
GRANT CONNECT, RESOURCE, CREATE ANY DIRECTORY TO lob_user;

您会在示例代码文件 lob_db.sql 中找到前两个语句和该部分中出现的设置 store 模式的其他语句。

以下语句创建一个名为 SAMPLE_FILES_DIR 的目录,该目录指向服务器硬盘驱动器上的 C:\sample_files 目录;您必须在硬盘驱动器的 C: 分区中创建 sample_files 目录,并将 textContent.txt 和 binaryContent.doc 文件复制到 C:\sample_files 中。

CREATE OR REPLACE DIRECTORY SAMPLE_FILES_DIR AS 'C:\sample_files';

注意:textContent.txt 和 binaryContent.doc 文件包含莎士比亚戏剧 Macbeth 中的引文。您不久将看到把这两个文件的内容复制到数据库中。

下一语句授予公众读取权限,以便所有用户均可读取 SAMPLE_FILES_DIR 的内容:
GRANT READ ON DIRECTORY SAMPLE_FILES_DIR TO PUBLIC;

下一语句以 lob_user 的身份连接:

CONNECT lob_user/lob_password;

您将看到本文使用了三个表:

  • clob_content:包含一个名为 clob_column 的 CLOB 列。该列用于存储 textContent.txt 文件中包含的字符数据。
  • blob_content:包含一个名为 blob_column 的 BLOB 列。该列用于存储 binaryContent.doc 文件中存储的二进制数据。
  • bfile_content:包含一个名为 bfile_column 的 BFILE 列。该列用于存储两个外部文件的指针。
以下语句创建 clob_content、blob_content 和 bfile_content 等表:
CREATE TABLE clob_content (
id          INTEGER PRIMARY KEY,
clob_column CLOB NOT NULL
);

CREATE TABLE blob_content (
id          INTEGER PRIMARY KEY,
blob_column BLOB NOT NULL
);

CREATE TABLE bfile_content (
id           INTEGER PRIMARY KEY,
bfile_column BFILE NOT NULL
);

如果您创建了这些表所用的模式不是 lob_user 的模式,那么您将需要修改稍后的示例程序中的模式名称。

下两条语句向 clob_content 和 blob_content 表中添加一个空的 CLOB 和 BLOB:

INSERT INTO clob_content (
id, clob_column
) VALUES (
1, EMPTY_CLOB()
);

INSERT INTO blob_content (
id, blob_column
) VALUES (
1, EMPTY_BLOB()
);

下列 PL/SQL 语句将文件 textContent.txt 中的文本加载到 clob_content 表中,将文件 binaryContent.doc 中的二进制数据加载到 blob_content 表中:

DECLARE
my_clob  CLOB;
my_blob  BLOB;
my_bfile BFILE;
BEGIN
-- load the CLOB
my_bfile := BFILENAME('SAMPLE_FILES_DIR', 'textContent.txt');
SELECT clob_column
INTO my_clob
FROM clob_content
WHERE id = 1 FOR UPDATE;
DBMS_LOB.FILEOPEN(my_bfile, dbms_lob.file_readonly);
DBMS_LOB.LOADFROMFILE(my_clob, my_bfile, DBMS_LOB.GETLENGTH(my_bfile), 1, 1);

-- load the BLOB
my_bfile := BFILENAME('SAMPLE_FILES_DIR', 'binaryContent.doc');
SELECT blob_column
INTO my_blob
FROM blob_content
WHERE id = 1 FOR UPDATE;
DBMS_LOB.FILEOPEN(my_bfile, dbms_lob.file_readonly);
DBMS_LOB.LOADFROMFILE(my_blob, my_bfile, DBMS_LOB.GETLENGTH(my_bfile), 1, 1);

DBMS_LOB.FILECLOSEALL();
COMMIT;
END;
/

下一条语句使 bfile_content 表中的 BFILE 指向位于 SAMPLE_FILES_DIR 目录中的 textContent.txt 文件:

INSERT INTO bfile_content (
id,
bfile_column
) VALUES (
  1,
BFILENAME('SAMPLE_FILES_DIR', 'textContent.txt')
);

使用 C# 和 VB.NET 从 LOB 中读取数据

检索 LOB 有两种方法:

  1. 使用 LOB 定位器延迟 LOB 检索:ODP.NET 在数据库服务器上检索 LOB 的指针。在应用程序开始读取 LOB 之前不检索实际的 LOB 数据。对于 CLOB,应使用 Oracle.DataAccess.Types.OracleClob 类的对象存储使用 OracleDataReader 对象的 GetOracleClob() 方法读取的定位器,然后使用 Read() 方法访问 OracleClob 中存储的数据。对于 BLOB,应使用 Oracle.DataAccess.Types.OracleBlob 对象和 GetOracleBlob() 方法。
  2. 立即检索所有或大量 LOB 数据:ODP.NET 将在 SELECT 语句执行时检索所有 LOB 的 LOB 数据。对于 CLOB,应使用 OracleDataReaderGetString()GetChars()GetValue()GetOracleString() 方法读取数据。对于 BLOB,应使用 GetBytes()GetValue()GetValues()GetOracleBinary() 方法。
在第二种情况下,第一个数据库往返从 LOB 读取的数据量取决于 OracleDataReader 对象的 InitialLOBFetchSize 属性的设置,它的值从 OracleCommand 对象中继承。InitialLOBFetchSize 的默认值为 0 — 即 LOB 数据检索将推迟到程序显式请求该数据(即第一种情况)时进行。如果将 InitialLOBFetchSize 更改为大于零的值,则在一个往返中将立即检索 LOB 数据,最多为在 InitialLOBFetchSize 中指定的字节或字符数。

此参数影响 SELECT 语句执行中的所有 LOB。例如,如果将 InitialLOBFetchSize 设置为 5K,且在 SELECT 语句执行中将检索 10 个 LOB,则在一个数据库往返中将检索这 10 个 LOB 中每个 LOB 的前 5K。当前,10.1.0.2.0 版的 ODP.NET 中 InitialLOBFetchSize 的最大设置为 32KB。Oracle 将在未来版本中将此最大大小增大为 2GB。

注意:如果更改 InitialLOBFetchSize(默认值 0),则您只能使用上面提到的方法 2 中的访问器从 CLOB 中读取数据 — 不过 Oracle 计划移除该限制。在未来的 ODP.NET 版本中,您将能够使用这两个方法来检索 LOB。

如果您选择的所有 LOB 的数据量不大,且选择了很多 LOB,则通过更改 InitialLOBFetchSize(默认值 0),您可能获得更出色的立即检索 LOB 数据性能。如果使用 InitialLOBFetchSize,则应将其设置为一个略大于所选 LOB 大小的 80% 的值。例如,如果行中 LOB 大小的 80% 小于或等于 1KB,则应将 InitialLOBFetchSize 设置为 1KB。由于结果将取决于网络性能、延迟、数据大小等因素,因此应试验您的设置以发现 InitialLOBFetchSize 的最优设置。

更改 InitialLOBFetchSize 的默认值 0 时,将进行立即 LOB 检索。当保留 InitialLOBFetchSize 的默认值零 0 时,将进行延迟 LOB 检索。下表提供了决定使用延迟 LOB 检索还是立即 LOB 检索时要考虑的原则。

在以下情况下使用延迟 LOB 检索 在以下情况下使用立即 LOB 检索
客户端和数据库服务器之间的网络带宽不足 网络带宽充足
您不需要立即对大部分 LOB 数据进行立即访问,而是可以随着时间的推移来检索它 您需要在选中 LOB 数据时立即读取几乎所有这些数据
您正在执行更新、插入或删除,不打算读取 LOB N/A

使用延迟 LOB 检索从 LOB 中读取数据

接下来,我们将逐步完成四个示例程序(使用 LOB 定位器读取先前存储在 clob_content.clob_column 中的文本和存储在 blob_content.blob_column 中的二进制数据)中的主要步骤。这四个程序如下所示:
  1. ClobExample1.cs,一个从 clob_content.clob_column 中读取数据的 C# 程序
  2. ClobExample1.vb,与 ClobExample1.cs 相同,但用 VB.NET 编写
  3. BlobExample1.cs,一个从 blob_content.blob_column 中读取数据的 C# 程序
  4. BlobExample1.vb,与 BlobExample1.cs 相同,但用 VB.NET 编写。
注意:有关如何编译 C# 和 VB.NET 程序的信息,请阅读我的技术文章“在 .NET 中使用 Oracle 数据库事务”。

第 1 步

ClobExample1.cs 中的第 1 步从 clob_content 表中读取行

myOracleCommand.CommandText =
"SELECT id, clob_column " +
"FROM clob_content " +
"WHERE id = 1";
OracleDataReader myOracleDataReader =
myOracleCommand.ExecuteReader();
myOracleDataReader.Read();

在 ClobExample1.vb 中,VB.NET 代码为

myOracleCommand.CommandText = _
"SELECT id, clob_column " & _
"FROM clob_content " & _
"WHERE id = 1"
Dim myOracleDataReader As _
OracleDataReader = myOracleCommand.ExecuteReader()
myOracleDataReader.Read()

BlobExample1.cs 中的第 1 步从 blob_content 表中读取行:

myOracleCommand.CommandText =
"SELECT id, blob_column " +
"FROM blob_content " +
"WHERE id = 1";
OracleDataReader myOracleDataReader =
myOracleCommand.ExecuteReader();
myOracleDataReader.Read();

在 BlobExample1.vb 中,VB.NET 代码为

myOracleCommand.CommandText = _
"SELECT id, blob_column " & _
"FROM blob_content " & _
"WHERE id = 1"
Dim myOracleDataReader As _
OracleDataReader = myOracleCommand.ExecuteReader()
myOracleDataReader.Read()

第 2 步

ClobExample1.cs 中的第 2 步将 LOB 定位器复制给 OracleClob 对象。使用 myOracleDataReader.GetOracleClob() 方法取得定位器:

OracleClob myOracleClob = myOracleDataReader.GetOracleClob(1);

在 ClobExample1.vb 中,VB.NET 代码为

Dim myOracleClob As _
OracleClob = myOracleDataReader.GetOracleClob(1)

BlobExample1.cs 中的第 2 步将 LOB 定位器复制给 OracleBlob 对象。使用 myOracleDataReader.GetOracleBlob() 方法取得定位器:

OracleBlob myOracleBlob = myOracleDataReader.GetOracleBlob(1);

在 BlobExample1.vb 中,VB.NET 代码为

Dim myOracleBlob As _
OracleBlob = myOracleDataReader.GetOracleBlob(1)

第 3 步

ClobExample1.cs 中的第 3 步使用 OracleClob 对象的 Read() 方法取得 CLOB 数据。Read() 方法有两个版本:

int Read(byte [] byteArray, int offset, int count)
int Read(char [] charArray, int offset, int count)
其中:
  • 返回的 int 是读取的字节或字符数
  • byteArraycharArray 是将数据读入的数组
  • offset 是将数据写到的数组中的位置
  • count 是要读取的字节或字符数。
在 ClobExample1.cs 的以下代码中您将看到,从 CLOB 读取字符并将其写入名为 charArray 的字符数组中。此示例代码将在每个数据库往返中一次读取 CLOB 50 个字符,直到读取了整个 CLOB。
char [] charArray = new char[50];
int numCharsRead; 
while ((numCharsRead = myOracleClob.Read(charArray, 0, 50)) > 0)
{
Console.WriteLine("numCharsRead = " + numCharsRead);
string clobData = new string(charArray, 0, numCharsRead);
Console.WriteLine("clobData = " + clobData);
}

在 ClobExample1.vb (VB.NET) 中:

Dim charArray(50) As char
Dim numCharsRead As Integer
numCharsRead = myOracleClob.Read(charArray, 0, 50)
Do While (numCharsRead > 0)
Console.WriteLine("numCharsRead = " & numCharsRead)
Dim clobData As New string(charArray, 0, numCharsRead)
Console.WriteLine("clobData = " & clobData)
numCharsRead = myOracleClob.Read(charArray, 0, 50)
Loop

BlobExample1.cs 中的第 3 步使用 OracleBlob 对象的 Read() 方法。Read() 方法只有一个版本:

int Read(byte [] byteArray, int offset, int count)

在 BlobExample1.cs 的以下 C# 代码中您将看到,从 BLOB 读取字符并将其写入名为 byteArray 的字符数组中。此示例代码将在每个数据库往返中一次读取 BLOB 50 个字符,直到读取了整个 BLOB。

byte [] byteArray = new byte[50];
Console.WriteLine("byteArray.Length = " + byteArray.Length);
int numBytesRead;
while ((numBytesRead = myOracleBlob.Read(byteArray, 0, 50)) > 0)
{
Console.WriteLine("numBytesRead = " + numBytesRead);
}

在 BlobExample1.vb 中,VB.NET 代码为

Dim byteArray(50) As byte
Dim numBytesRead As Integer
numBytesRead = _
myOracleBlob.Read(byteArray, 0, 50)
Do While (numBytesRead > 0)
Console.WriteLine("numBytesRead = " & numBytesRead)
numBytesRead = _
myOracleBlob.Read(byteArray, 0, 50)
Loop

使用立即 LOB 检索从 LOB 中读取数据

现在,我将逐步完成四个示例程序(使用立即 LOB 检索读取先前存储在 clob_content.clob_column 中的文本和存储在 blob_content.blob_column 中的二进制数据)中的主要步骤。这四个程序如下所示:
  • ClobExample2.cs,一个从 clob_content.clob_column 中读取数据的 C# 程序
  • ClobExample2.vb,与上一个程序相同,但用 VB.NET 编写
  • BlobExample2.cs,一个从 blob_content.blob_column 中读取数据的 C# 程序
  • BlobExample2.vb,与上一个程序相同,但用 VB.NET 编写。
我还将在第 1 步中向您演示如何更改 InitialLOBFetchSize。正如我在前面提到的,将 InitialLOBFetchSize 更改为一个大于零的值将导致立即检索数目最大为在 InitialLOBFetchSize 中指定的字节或字符数的 LOB 数据。

第 1 步

第 1 步将 InitialLOBFetchSize 设置为 1,000 个字节。在 ClobExample2.cs 和 BlobExample2.cs 中,C# 代码为

myOracleCommand.InitialLOBFetchSize = 1000;

注意,是在 OracleCommand 对象上设置 InitialLOBFetchSize。在 ClobExample2.vb 和 BlobExample2.vb 中,VB.NET 代码为

myOracleCommand.InitialLOBFetchSize = 1000

第 2 步

第 2 步与前面的延迟 LOB 检索示例显示的第 1 步相同。

第 3 步

ClobExample2.cs 中的第 3 步使用 GetString() 方法从 CLOB 中取得数据并显示该数据:

String clobData = myOracleDataReader.GetString(1);
Console.WriteLine("clobData = " + clobData);

在 ClobExample2.vb 中,VB.NET 代码为

Dim clobData As string = myOracleDataReader.GetString(1)
Console.WriteLine("clobData = " & clobData)

BlobExample2.cs 中的第 3 步使用 GetBytes() 方法从 BLOB 中取得数据并显示读取的字节数:

byte [] byteArray = new byte[1000];
long numBytesRead = myOracleDataReader.GetBytes(1, (long) 0, byteArray, 0, 1000);
Console.WriteLine("numBytesRead = " + numBytesRead);

在 BlobExample2.vb 中,VB.NET 代码为

Dim byteArray(1000) As byte
Dim numBytesRead As long = _
myOracleDataReader.GetBytes(1, 0, byteArray, 0, 1000)
Console.WriteLine("numBytesRead = " & numBytesRead)

使用 C# 和 VB.NET 写入 LOB

使用 OracleDataReader 对象时有两种方法可以写入 LOB:

  • 对于 CLOB,调用 OracleDataReaderGetOracleClobForUpdate() 方法。对于 BLOB,调用 GetOracleBlobForUpdate() 方法。
  • FOR UPDATE 子句添加到 SELECT 语句,然后调用 GetOracleClob()GetOracleBlob() 方法取得 CLOB 或 BLOB。
至于选择哪种方法完全取决于个人偏好。方法之间不存在性能优劣。对于任何一种方法,当您在 OracleClobOracleBlob 中使用 CLOB 或 BLOB 定位器后,应使用 OracleClobOracleBlobWrite() 方法写入 LOB。使用定位器访问 LOB 的优点是,在写入 LOB 之前,最初不必将数据下载到中间层。

使用方法 1 写入 CLOB

我将逐步完成两个示例程序(使用方法 1 写入 clob_content.clob_column 中的 CLOB)中的主要步骤。这两个程序如下所示:

  • ClobExample3.cs,一个写入 clob_content.clob_column 的 C# 程序
  • ClobExample3.vb,与上一个程序一样,但用 VB 编写。
由于写入 BLOB 的步骤相似,因此我只演示写入 CLOB 的代码。

第 1 步

必须在 OracleTransaction 对象的上下文中执行所有 LOB 更新。在 ClobExample3.cs 中,C# 代码为

OracleTransaction myOracleTransaction = myOracleConnection.BeginTransaction();

在 ClobExample3.vb 中,VB.NET 代码为

Dim myOracleTransaction As OracleTransaction = _
myOracleConnection.BeginTransaction()

第 2 步

第 2 步是读取行,它与前面的“使用延迟 LOB 检索从 LOB 中读取数据”部分中的第 1 步相同。

第 3 步

第 3 步是使用 OracleDataReaderGetOracleClobForUpdate() 方法取得 LOB 定位器。在 ClobExample3.cs 中,C# 代码为

OracleClob myOracleClob = myOracleDataReader.GetOracleClobForUpdate(1);

在 ClobExample3.vb 中,VB.NET 代码为

Dim myOracleClob As _
OracleClob = myOracleDataReader.GetOracleClobForUpdate(1)

第 4 步

第 4 步是使用 OracleClob 对象的 Write() 方法写入 CLOB。Write() 方法有两个版本:

Write(byte [] byteArray, int offset, int count)
Write(char [] charArray, int offset, int count)

其中:

  • byteArraycharArray 是包含要写入 CLOB 的数据的数组
  • offset 是将数据写到 CLOB 中的位置
  • count 是要写入的字节或字符数。
在 ClobExample3.cs 的以下 C# 代码中,注意我首先使用 Erase() 方法删除了 myOracleClob 的当前内容;写入 myOracleClob 之前不必执行该操作,执行该操作只是为了删除现有文本。
myOracleClob.Erase();
string text = "It is the east, and Juliet is the Sun";
char [] charArray = text.ToCharArray();
myOracleClob.Write(charArray, 0, charArray.Length);
Console.WriteLine("myOracleClob.Value = " + myOracleClob.Value);

在 ClobExample3.vb 中,VB.NET 代码为

myOracleClob.Erase()
Dim text As string = "It is the east, and Juliet is the Sun"
Dim charArray() As char = text.ToCharArray()
myOracleClob.Write(charArray, 0, charArray.Length)
Console.WriteLine("myOracleClob.Value = " & myOracleClob.Value)

第 5 步

第 5 步是提交事务,以便将新文本永久存储在数据库中。在 ClobExample3.cs 中,C# 代码为

myOracleTransaction.Commit();

在 ClobExample3.vb 中,VB.NET 代码为

myOracleTransaction.Commit()

使用方法 2 写入 CLOB

现在,我们将逐步完成两个示例程序(使用方法 2 写入 clob_content.clob_column 中的 CLOB)中的主要步骤。这两个程序如下所示:

  • ClobExample4.cs,一个写入 clob_content.clob 的 C# 程序
  • ClobExample4.vb,与上一个程序相同,但用 VB.NET 编写。
只有第 2 步和第 3 步与方法 1 中所示步骤不同。

第 2 步

第 2 步从 clob_content 中读取行。对于方法 2,将 FOR UPDATE 子句添加到 SELECT 语句。在 ClobExample4.cs 中,C# 代码为
myOracleCommand.CommandText =
"SELECT id, clob_column " +
"FROM clob_content " +
"WHERE id = 1 FOR UPDATE";
OracleDataReader myOracleDataReader =
myOracleCommand.ExecuteReader();
myOracleDataReader.Read();

在 ClobExample4.vb 中,VB.NET 代码为

myOracleCommand.CommandText = _
"SELECT id, clob_column " & _
"FROM clob_content " & _
"WHERE id = 1 FOR UPDATE"
Dim myOracleDataReader As _
OracleDataReader = myOracleCommand.ExecuteReader()
myOracleDataReader.Read()

第 3 步

第 3 步取得 CLOB 定位器。在 ClobExample4.cs 中,C# 代码为
OracleClob myOracleClob = myOracleDataReader.GetOracleClob(1);

在 ClobExample4.vb 中,VB.NET 代码为

Dim myOracleClob As OracleClob = _
myOracleDataReader.GetOracleClob(1)

以下是该步骤与前一方法中所示步骤的差别:此处我调用 GetOracleClob(),而前面我调用了 GetOracleClobForUpdate()。由于第 2 步中使用了 FOR UPDATE 子句,因此我不必使用 GetOracleClobForUpdate() — 我只需调用 GetOracleClob() 并开始写入 CLOB。一旦拥有 CLOB 定位器,写入 CLOB 的步骤则与上面的方法 1 完全相同。

使用 C# 和 VB.NET 从 BFILE 中读取数据

BFILE 存储文件系统中文件的指针,您可以通过该指针访问该文件。我将逐步完成两个示例程序(读取由 bfile_content.bfile_column 中的 BFILE 指向的 textContent.txt 文件中的文本)中的主要步骤。这两个程序如下所示:

  • BfileExample1.cs,一个 C# 程序
  • BfileExample1.vb,上一程序的 VB.NET 版本。
第 1 步

第 1 步从 bfile_content 表中读取行。在 BfileExample1.cs,C# 代码为
myOracleCommand.CommandText =
"SELECT id, bfile_column " +
"FROM bfile_content " +
"WHERE id = 1";
OracleDataReader myOracleDataReader =
myOracleCommand.ExecuteReader();
myOracleDataReader.Read();

在 BfileExample1.vb 中,VB.NET 代码为

myOracleCommand.CommandText = _
"SELECT id, bfile_column " & _
"FROM bfile_content " & _
"WHERE id = 1"
Dim myOracleDataReader As OracleDataReader = _
myOracleCommand.ExecuteReader()
myOracleDataReader.Read()

第 2 步

第 2 步通过调用 OracleDataReader 对象的 GetOracleBFile() 方法取得 BFILE。在 BfileExample1.cs 的以下 C# 代码中您将看到,我还将显示目录名、文件名以及文件是否存在:
OracleBFile myOracleBFile = myOracleDataReader.GetOracleBFile(1);
Console.WriteLine("myOracleBFile.DirectoryName = " +
myOracleBFile.DirectoryName);
Console.WriteLine("myOracleBFile.FileName = " +
myOracleBFile.FileName);
Console.WriteLine("myOracleBFile.FileExists = " +
myOracleBFile.FileExists);

在 BfileExample1.vb 中,VB.NET 代码为

Dim myOracleBFile As OracleBFile = _
myOracleDataReader.GetOracleBFile(1)
Console.WriteLine("myOracleBFile.DirectoryName = " & _
myOracleBFile.DirectoryName)
Console.WriteLine("myOracleBFile.FileName = " & _
myOracleBFile.FileName)
Console.WriteLine("myOracleBFile.FileExists = " & _
myOracleBFile.FileExists)

第 3 步

BfileExample1.cs 中的第 3 步打开 BFILE:

myOracleBFile.OpenFile();

在 BfileExample1.vb 中,VB.NET 与上一程序相同。

第 4 步

BfileExample1.cs 中的第 4 步使用 Read() 方法从 BFILE 中读取数据。在以下代码中您将看到,BFILE 中的数据被读入名为 byteArrray 的字节数组中;同时,还使用 System.Text.Encoding.ASCII.GetString() 方法将该数组中的数据转换为字符串,以便在屏幕上显示数据:
byte [] byteArray = new byte[1000];
int offset = 0;
int numBytesRead;
while ((numBytesRead = myOracleBFile.Read(byteArray, offset, 1000-offset)) > 0)
{
Console.WriteLine("numBytesRead = " + numBytesRead);
String text =
System.Text.Encoding.ASCII.GetString(byteArray, 0, numBytesRead);
Console.WriteLine("text = " + text);
offset += numBytesRead;
}

在 BfileExample1.vb 中,VB.NET 代码为

Dim byteArray(1000) As byte
Dim offset As Integer = 0
Dim numBytesRead As Integer
numBytesRead = myOracleBFile.Read(byteArray, offset, 1000-offset)
Do While (numBytesRead > 0)
Console.WriteLine("numBytesRead = " & numBytesRead)
Dim text As string = _
System.Text.Encoding.ASCII.GetString(byteArray, 0, numBytesRead)
Console.WriteLine("text = " & text)
offset += numBytesRead
numBytesRead = myOracleBFile.Read(byteArray, offset, 1000-offset)
Loop                              

第 5 步

BfileExample1.cs 中的第 5 步使用 Close() 方法关闭 BFILE:

myOracleBFile.Close();                   

在 BfileExample1.vb 中,VB.NET 与上一程序相同。

结论

本文介绍了如何从 C# 和 VB.NET 访问大对象。您还了解了如何通过 BFILE 读取数据。


技术顾问兼作家 Jason Price 是 Microsoft 认证专家、Oracle 认证数据库管理员和应用程序开发人员,具有十多年的软件行业从业经验。他撰写了《Oracle 数据库 10g SQL》(McGraw-Hill/Osborne,2004)、《精通 C# 数据库编程》(Sybex,2004)、《精通 Visual C# .NET 编程》(Sybex,2003)、《Oracle9i JDBC 编程》(McGraw-Hill/Osborne,2002)和《使用 Oracle SQLJ 进行 Java 编程》(O'Reilly,2001)。

posted on 2005-08-09 10:45  [Fenghua]  阅读(1097)  评论(0编辑  收藏  举报

导航