使用 WCF 服务模型对 Oracle 数据库中具有大型数据类型的表完成操作
本部分包含有关如何从 WCF 服务模型调用 ReadLOB 和 UpdateLOB 操作的信息。 为包含 LOB 列的表和视图显示 ReadLOB 和 UpdateLOB 操作;是用于存储 Oracle 大型对象 (LOB) 数据的列。 有关适用于 Oracle 数据库的 Microsoft BizTalk 适配器支持的 Oracle LOB 数据类型以及 ReadLOB 和 UpdateLOB 操作的概述,请参阅 对包含 Oracle 数据库中 LOB 数据的表和视图的操作。
重要
LOB 数据列可以包含大量数据, (GB) 最多 4 GB。 使用 WCF 客户端对 LOB 列进行操作的一个重要限制是 WCF 服务模型仅支持在 ReadLOB 操作上流式传输数据,而不支持在 UpdateLOB 操作上。 这是因为 WCF 要求流式处理从服务模型运行,要流式传输的参数必须是其方向上的唯一参数。 除了 LOB 数据之外,UpdateLOB 操作还有两个其他 IN 参数, (列名和行筛选器) ;因此,WCF 服务模型中不支持流式处理。 因此,如果要使用大量数据更新 LOB 列,则可能需要使用 WCF 通道模型。 有关如何使用 WCF 通道模型通过 UpdateLOB 操作流式传输 LOB 数据的详细信息,请参阅 使用 WCF 通道模型流式处理 Oracle LOB 数据类型。
关于本主题中使用的示例
本主题中的示例使用 /SCOTT/CUSTOMER 表。 此表包含名为 PHOTO 的 BLOB 列。SDK 示例提供了生成此表的脚本。 有关 SDK 示例的详细信息,请参阅 SDK 中的示例。
WCF 客户端类
以下示例演示为 /SCOTT/CUSTOMER 表上的 ReadLOB 和 UpdateLOB 操作生成的 WCF 客户端类的方法签名。
public partial class SCOTTTableCUSTOMERClient : System.ServiceModel.ClientBase<SCOTTTableCUSTOMER>,
SCOTTTableCUSTOMER
{
public System.IO.Stream ReadLOB(string LOB_COLUMN, string FILTER);
public void UpdateLOB(string LOB_COLUMN, string FILTER, byte[] Stream);
}
注意
请注意, ReadLOB 返回数据流,但 UpdateLOB 不对流进行操作。
调用 ReadLOB 和 UpdateLOB 操作
ReadLOB 和 UpdateLOB 方法只能对单个数据库行中的单个 LOB 列进行操作。 设置以下参数以标识目标列/行。
参数 | 定义 |
---|---|
LOB_COLUMN | FILTER 参数标识的行内的目标列的名称;例如“PHOTO”。 |
FILTER | 指定目标行的 SQL SELECT 语句 WHERE 子句的内容;例如,“NAME='Kim Ralls'”。 筛选器必须指定一行,并且只能指定一行。 如果筛选器匹配多个行: - ReadLOB 返回第一个匹配行的 LOB 数据。 - UpdateLOB 引发异常。 |
注意
ReadLOB 返回的流不支持 Seek。 这意味着 也不支持 Length 等属性。
注意
必须在事务范围内执行 UpdateLOB 操作。 此外,在执行 UpdateLOB 操作之前,必须将 UseAmbientTransaction 绑定属性设置为 true。
以下代码演示如何使用 WCF 客户端从文件更新 /SCOTT/CUSTOMER 表中的 BLOB PHOTO 列,并将新列数据读回文件。 可以在 SDK 示例中找到完整的示例。 有关 SDK 示例的详细信息,请参阅 SDK 中的示例。
using System;
using System.Collections.Generic;
using System.Text;
using System.Transaction;
// Include for file streaming
using System.IO;
// Add WCF, WCF LOB Adapter SDK, and Oracle Database adapter namepaces
using System.ServiceModel;
using Microsoft.ServiceModel.Channels;
using Microsoft.Adapters.OracleDB;
// Include this namespace for the WCF channel model
using System.ServiceModel.Channels;
// Include this namespace for the WCF LOB Adapter SDK and Oracle Database adapter exceptions
using Microsoft.ServiceModel.Channels.Common;
using CustomerTablens = microsoft.lobservices.oracledb._2007._03;
namespace OracleLobOpsSnippetSM
{
class Program
{
static void Main(string[] args)
{
try
{
OracleDBBinding binding = new OracleDBBinding();
binding.UseAmbientTransaction = true; //set this to true for UpdateLOB operation
EndpointAddress endpointAddress = new EndpointAddress("oracleDB://ADAPTER");
using (SCOTTTableCUSTOMERClient customerTableClient =
new SCOTTTableCUSTOMERClient(binding, endpointAddress))
{
customerTableClient.ClientCredentials.UserName.UserName = "SCOTT";
customerTableClient.ClientCredentials.UserName.Password = "TIGER";
// Open the client to read the LOB data back
customerTableClient.Open();
// Add a photo to the customer record
using (FileStream fs = new FileStream("SamplePhoto.jpg", FileMode.Open))
{
Console.WriteLine("Updating photo");
int count = 0;
byte[] photo = new byte[fs.Length];
while ((count += fs.Read(photo, count, (int) (((fs.Length-count)>4096)? 4096:fs.Length-count))) \< fs.Length) ;
// UpdateLOB operation must be performed within a transaction scope
using(TransactionScope tx = new TransactionScope())
{
customerTableClient.UpdateLOB("PHOTO", "NAME='Kim Ralls'", photo);
Console.WriteLine("Photo updated");
tx.Complete();
}
}
// Read the data back and store it to another file
using (FileStream fs = new FileStream("PhotoCopy.jpg", FileMode.Create))
{
Console.WriteLine("Reading photo data");
Stream photoStream = customerTableClient.ReadLOB("PHOTO", "NAME='Kim Ralls'");
Console.WriteLine("Photo data read -- writing to PhotoCopy.jpg");
int count;
int length = 0;
byte[] buffer = new byte[4096];
while ((count = photoStream.Read(buffer, 0, 4096)) > 0)
{
fs.Write(buffer, 0, count);
length+=count;
}
Console.WriteLine("{0} bytes written to PhotoCopy.jpg", length);
}
}
Console.WriteLine("Photo updated and read back -- Hit <RETURN> to end");
Console.ReadLine();
}
catch (Exception ex)
{
// handle exception
Console.WriteLine("Exception caught: " + ex.Message);
}
}
}
}