WCF サービス モデルを使用して Oracle Database の大きなデータ型を持つテーブルに対する操作を完了する
このセクションでは、WCF サービス モデルから ReadLOB および UpdateLOB 操作を呼び出す方法について説明します。 READLOB および UpdateLOB 操作は、LOB 列を含むテーブルとビューに対して表示されます。は、Oracle ラージ オブジェクト (LOB) データの格納に使用される列です。 Microsoft BizTalk Adapter for Oracle Database でサポートされる Oracle LOB データ型と ReadLOB および UpdateLOB 操作の概要については、「 Oracle Database の LOB データを含むテーブルおよびビューに対する操作」を参照してください。
重要
LOB データ列には、最大 4 ギガバイト (GB) の大量のデータを含めることができます。 WCF クライアントを使用して LOB 列を操作する場合の大きな制限は、WCF サービス モデルが UpdateLOB 操作ではなく、ReadLOB 操作でのデータ ストリーミングのみをサポートすることです。 これは、WCF では、ストリーミングをサービス モデルから機能させるには、ストリーミングするパラメーターがその方向の唯一のパラメーターである必要があるためです。 UpdateLOB 操作には、LOB データに加えて、他の 2 つの 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);
}
Note
ReadLOB はデータ ストリームを返しますが、UpdateLOB はストリームに対して動作しないことに注意してください。
ReadLOB 操作と UpdateLOB 操作の呼び出し
ReadLOB メソッドと UpdateLOB メソッドはどちらも、1 つのデータベース行の 1 つの LOB 列でのみ動作できます。 ターゲット列/行を識別するには、次のパラメーターを設定します。
パラメーター | 定義 |
---|---|
LOB_COLUMN | FILTER パラメーターによって識別される行内のターゲット列の名前。たとえば、"PHOTO" です。 |
FILTER | ターゲット行を指定する SQL SELECT ステートメント WHERE 句の内容。たとえば、"NAME='Kim Ralls' などです。 フィルターでは、1 行のみを指定する必要があります。 フィルターが複数の行と一致する場合: - ReadLOB は 、最初に一致する行の LOB データを返します。 - UpdateLOB は 例外をスローします。 |
Note
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);
}
}
}
}