使用 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 操作

ReadLOBUpdateLOB 方法只能对单个数据库行中的单个 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);  
            }  
        }  
    }  
}  

另请参阅

使用 WCF 服务模型开发 Oracle 数据库应用程序