Microsoft BizTalk Adapter for Oracle Database 會以作業的形式呈現程式、函式和套件。 在 WCF 服務模型中,這些作業會以 WCF 用戶端上的方法表示。 WCF 服務模型和 Oracle 資料庫配接器:
支援函式。 Oracle 函式的 RETURN 值會顯示為 WCF 用戶端方法的傳回值。 Oracle 參數會以合適的方向呈現為 WCF 用戶端方法的參數(如下所定義)。
支援程式。 Oracle 程式的第一個 OUT 參數會呈現為 WCF 用戶端方法的傳回值。 所有其他 Oracle 參數都會顯示為參數(依如下規定的適當方向),然後傳送到 WCF 用戶端方法。
支援 Oracle 套件。 作業的名稱及其參數類型的命名空間會以封裝名稱限定。
支援多載函式和程式。
針對程式和函式,支援基本 Oracle 資料類型的 IN、OUT 和 IN OUT 參數。 OUT 參數會呈現為 WCF 用戶端方法上的 out 參數,而 IN OUT 參數會呈現為 ref 參數。
支援程式和函式的 IN、OUT 和 IN OUT REF CURSOR 參數,以及函式 RETURN 值。 如需詳細資訊,請參閱 使用WCF服務模型在 Oracle 資料庫中使用 REF CURSORS 執行作業。
支援程式和函式的 IN、OUT 和 IN OUT RECORD 類型參數,以及函式 RETURN 值。 如需詳細資訊,請參閱 使用WCF服務模型在 Oracle 資料庫中使用 RECORD 類型執行作業。
關於本主題中使用的範例
本主題中的範例會使用 /SCOTT/Package/ACCOUNT_PKG/GET_ACCOUNT 多載程式。 此程式會根據帳戶標識碼或帳戶名稱,從 SCOTT/ACCOUNT 數據表讀取記錄。 SDK 範例會提供產生此程式和數據表的腳本。 如需 SDK 範例的詳細資訊,請參閱 SDK 中的範例。
WCF 用戶端類別
下表顯示 WCF 用戶端的名稱,以及針對 Oracle 資料庫配接器所呈現之程式、函式和套件所產生的方法。 除非多載函式或程式,否則單一 WCF 用戶端會用來叫用架構中的所有函式、架構中的所有程式,或封裝中的所有函式和程式。
Oracle 構件 | WCF 用戶端作業名稱 | 範例 |
---|---|---|
程序 | [SCHEMA]ProcedureClient.[PROC_NAME] | SCOTTProcedureClient.MYPROC |
功能 | [SCHEMA]FunctionClient。[FUNC_NAME] | SCOTTProcedureClient.MYFUNC |
封裝(程式或函式) | [SCHEMA] Package [PACKAGE_NAME] Client。[PROC_NAME 或 FUNC_NAME] | SCOTTPackageMYPACKAGEClient.MYPROC |
[SCHEMA] = Oracle 構件的集合; 例如,SCOTT。
[PROC_NAME] = Oracle 程序的名稱;例如,MYPROC。
[FUNC_NAME] = Oracle 函式的名稱;例如,MYFUNC。
[PACKAGE_NAME] = Oracle 封裝的名稱。
Oracle Database 配接器代表 Oracle RECORD 類型參數和傳回值,以及 REF CURSOR 參數所傳回的結果集,做為包含 Oracle 記錄之數據列數據(或字段)的複雜 XML 類型。 在 WCF 服務模型中,每個 XML 類型都會以 .NET 類別表示;類別的屬性代表 RECORD 類型或 REF CURSOR 結果集的欄位。 Oracle RECORD 類型一律會以強類型 .NET 類別表示。 不過,REF CURSOR 結果集的表示方式可根據 REF CURSOR 本身是被宣告為強型別或弱型別而分為強型別或弱型別記錄。 代表 REF CURSOR 或 RECORD 類型參數(或傳回值)的類別會根據程式、函式或封裝,在唯一命名空間中產生。 下表顯示這些命名空間。
Oracle 構件 | Namespace | 範例 |
---|---|---|
程序 | [BASE_NS]。 [SCHEMA]。程式。[PROC_NAME] | microsoft.lobservices.oracledb._2007._03.SCOTT.Procedure.MYPROC |
功能 | [BASE_NS]。 [SCHEMA]。功能。[FUNC_NAME] | microsoft.lobservices.oracledb._2007._03.SCOTT.Function.MYFUNC |
封裝 (程序) | [BASE_NS]。 [SCHEMA]。包。[PACKAGE_NAME]。[PROC_NAME] | microsoft.lobservices.oracledb._2007._03.SCOTT.Package.MYPACKAGE.MYPROC |
套件 (函數) | [BASE_NS]。 [SCHEMA].封裝。[PACKAGE_NAME].[FUNC_NAME] | microsoft.lobservices.oracledb._2007._03.SCOTT.Package.MYPACKAGE.MYFUNC |
一般資料集(弱類型) | [BASE_NS] | microsoft.lobservices.oracledb._2007._03 |
[BASE_NS] = 基底配接器命名空間;microsoft.lobservices.oracledb._2007._03。
[SCHEMA] = Oracle 構件的集合; 例如,SCOTT。
[PROC_NAME] = Oracle 程序的名稱;例如;MYPROC。
[FUNC_NAME] = Oracle 函式的名稱;例如 MYFUNC。
[PACKAGE_NAME] = Oracle 封裝的名稱。
如需這些命名空間如何用於 RECORD 參數的資訊,請參閱 使用 WCF 服務模型在 Oracle 資料庫中使用 RECORD 類型執行作業。 如需這些命名空間如何用於 REF CURSOR 參數的資訊,請參閱 使用 WCF 服務模型在 Oracle 資料庫中使用 REF CURSORS 執行作業。
一般而言,Oracle 參數和傳回值會在 WCF 用戶端方法中對應如下:
Oracle IN 參數會對應至 .NET (輸入) 參數。
Oracle OUT 參數會對應至 .NET out 參數。
Oracle IN OUT 參數會對應至 .NET ref 參數。
函式 RETURN 值會映射到方法的傳回值。
不過,有兩個重要的例外狀況存在:
Oracle IN OUT REF CURSOR 參數會分割成輸入字串和輸出 (out) 記錄集。 這是因為 Oracle 資料庫配接器將 IN REF CUSROR 參數表示為字串,而 OUT REF CURSOR 參數做為複雜類型(記錄集),因此這些參數無法合併成單一參數。
Oracle 程式中的第一個 OUT 參數會對應至 WCF 用戶端方法的傳回值。 這是標準 WCF 行為。
下列範例顯示簡單 Oracle 程式的一部分(載入於 SCOTT 架構中),以及用來呼叫此程式所產生的 WCF 用戶端方法簽名。 Oracle 程式有三個 IN 參數、三個 IN OUT 參數和三個 OUT 參數:不過,WCF 用戶端方法不會對應第一個 OUT 參數的參數。 相反地,它對應於方法的傳回值。
CREATE or REPLACE PROCEDURE Sample_Procedure
(
INNUMBER IN NUMBER,
INVARCHAR IN VARCHAR2,
INDATE IN DATE,
INOUTNUMBER IN OUT NUMBER,
INOUTVARCHAR IN OUT VARCHAR,
INOUTDATE IN OUT DATE,
OUTNUMBER OUT NUMBER,
OUTVARCHAR OUT VARCHAR2,
OUTDATE OUT DATE
) AS
BEGIN
...
END;
/
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public partial class SCOTTProcedureClient : System.ServiceModel.ClientBase<SCOTTProcedure>, SCOTTProcedure {
public System.Nullable<decimal> SAMPLE_PROCEDURE
(
System.Nullable<decimal> INNUMBER,
string INVARCHAR,
System.Nullable\<System.DateTime\> INDATE,
ref System.Nullable<decimal> INOUTNUMBER,
ref string INOUTVARCHAR,
ref System.Nullable\<System.DateTime\> INOUTDATE,
out string OUTVARCHAR,
out System.Nullable\<System.DateTime\> OUTDATE
);
}
支援多載程式、函式和套件
Oracle Database 配接器藉由將唯一字串附加至節點 ID 及其針對每個重載的元件呈現的命名空間,以支援重載的程式、函數和封裝。 這個字串在第一個多載中是「overload1」,在下一個多載中是「overload2」,依此類推。
在 WCF 服務模型中,每個多載程式或函式都會由唯一的 WCF 用戶端表示。 這與非多載案例不同,其中 SCHEMA 中的所有函式、SCHEMA 中的所有程式,或 PACKAGE 中的所有程式和函式都是由相同的 WCF 用戶端叫用。 下表顯示針對多載程式、函式和封裝所產生的 WCF 用戶端名稱和方法。
Oracle 工件 | WCF 用戶端名稱 | 範例 |
---|---|---|
多載封裝 (程式) | [SCHEMA]Package[PACKAGE_NAME][PROC_NAME] ][OVERLOAD_ID]Client。[PROC_NAME] | SCOTTPackageMYPACKAGEMYPROCoverload1Client.MYPROC |
多載封裝 (函式) | [SCHEMA]Package[PACKAGE_NAME][FUNC_NAME] ][OVERLOAD_ID]Client。[FUNC_NAME] | SCOTTPackageMYPACKAGEMYFUNCoverload1Client.MYFUNC |
[SCHEMA] = Oracle 構件的集合; 例如,SCOTT。
[PROC_NAME] = Oracle 程序的名稱;例如;MYPROC。
[FUNC_NAME] = Oracle 函式的名稱;例如 MYFUNC。
[PACKAGE_NAME] = Oracle 封裝的名稱。
[OVERLOAD_ID] = 用於識別多載工件的唯一字符串:"overload1"、"overload2" 等等。
下表顯示針對多載程式、函式和封裝所產生的命名空間。
Oracle 構件 | Namespace | 範例 |
---|---|---|
封裝(程序) | [BASE_NS]。 [SCHEMA]。包。[PACKAGE_NAME]。[PROC_NAME][OVERLOAD_ID] | microsoft.lobservices.oracledb._2007._03.SCOTT.Package.MYPACKAGE.MYPROC.overload1 |
套件 (函式) | [BASE_NS]。 [SCHEMA].Package.[PACKAGE_NAME].[FUNC_NAME].[OVERLOAD_ID] | microsoft.lobservices.oracledb._2007._03.SCOTT.Package.MYPACKAGE.MYFUNC.overload1 |
通用記錄集(弱類型) | [BASE_NS] | microsoft.lobservices.oracledb._2007._03 |
[BASE_NS] = 基底配接器命名空間;microsoft.lobservices.oracledb._2007._03。
[SCHEMA] = Oracle 構件的集合; 例如,SCOTT。
[PROC_NAME] = Oracle 程序的名稱;例如;MYPROC。
[FUNC_NAME] = Oracle 函式的名稱;例如 MYFUNC。
[PACKAGE_NAME] = Oracle 封裝的名稱。
[OVERLOAD_ID] = 識別多載物件的唯一字串:"overload1"、"overload2" 等等。 字串中的數值是 Oracle 資料庫維護的工件重載 ID。
下列範例顯示針對 ACCOUNT_PKG封裝中多載GET_ACCOUNT程式所產生的 WCF 用戶端和方法簽章。 (包含 Oracle 宣告。這個範例示範如何為每個多載產生唯一的 WCF 用戶端,以及如何為每個客戶端產生的方法傳回唯一命名空間中的記錄集。
/* Procedure that takes account ID and returns record for existing account in the ACCOUNT table */
PROCEDURE get_account(aid IN account.acctid%TYPE, acct OUT account%ROWTYPE) ;
/* Procedure that takes account name and returns record for existing account in the ACCOUNT table */
PROCEDURE get_account(aname IN account.name%TYPE, acct OUT account%ROWTYPE) ;
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public partial class SCOTTPackageACCOUNT_PKGGET_ACCOUNToverload1Client : System.ServiceModel.ClientBase<SCOTTPackageACCOUNT_PKGGET_ACCOUNToverload1>, SCOTTPackageACCOUNT_PKGGET_ACCOUNToverload1 {
public microsoft.lobservices.oracledb._2007._03.SCOTT.Package.ACCOUNT_PKG.GET_ACCOUNT.overload1.ACCTRECORD GET_ACCOUNT(System.Nullable<decimal> AID);
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public partial class SCOTTPackageACCOUNT_PKGGET_ACCOUNToverload2Client : System.ServiceModel.ClientBase<SCOTTPackageACCOUNT_PKGGET_ACCOUNToverload2>, SCOTTPackageACCOUNT_PKGGET_ACCOUNToverload2 {
public microsoft.lobservices.oracledb._2007._03.SCOTT.Package.ACCOUNT_PKG.GET_ACCOUNT.overload2.ACCTRECORD GET_ACCOUNT(string ANAME);
}
叫用函式和程式
若要使用 WCF 用戶端叫用函式或程式,請執行下列步驟。
產生目標函式、程式或封裝的 WCF 用戶端類別。 這個類別應該包含您要在目標成品上叫用之作業的方法。
備註
在 [新增配接器服務參考 Visual Studio 外掛程式] 中,多載函式和程式會出現在 [可用類別和作業 ] 方塊中,顯示為 [NAME].1、[NAME].2、[NAME].3 等等,其中 [NAME] 是多載成品的名稱,而數值是 Oracle 資料庫上的多載標識符。
建立 WCF 用戶端類別的實例,並呼叫其方法來叫用函式或程式。
如需如何在 Oracle 資料庫配接器上建立 WCF 用戶端類別和叫用作業的詳細資訊,請參閱 使用 Oracle 資料庫配接器的 WCF 服務模型概觀。
Oracle Database 配接器會在 Oracle 資料庫上的交易內執行每個作業。
這很重要
代表 REF CURSOR 和 RECORD 型別參數的類別,或函式或程式中的傳回值(和套件)會在每個函式或程式的唯一命名空間中宣告。 例如,這表示在兩個不同函式中做為傳回值的 PACKAGE REF CURSOR 類型,將會在每個 WCF 用戶端方法的唯一命名空間中宣告。 您必須宣告個別變數來保存這些不同的傳回值,或在叫用其中一個 WCF 用戶端方法時適當地轉換變數。
下列範例示範如何呼叫多載 /SCOTT/Package/ACCOUNT_PKG/GET_ACCOUNT程式,以從 /SCOTT/ACCOUNT 數據表取得帳戶記錄。 首先,呼叫 /SCOTT/Package/ACCOUNT_PKG/CREATE_ACCOUNT 程式來建立新的記錄。 然後,通過呼叫 GET_ACCOUNT 的不同重載版本,將新記錄重新讀取兩次。 這個範例使用三個 WCF 用戶端,一個用於CREATE_ACCOUNT程式,另一個用於GET_ACCOUNT多載。 別名可用來區分用於傳回值GET_ACCOUNT的命名空間。 SDK 範例中提供完整的範例。 如需 SDK 範例的詳細資訊,請參閱 SDK 中的範例。
using System;
using System.Collections.Generic;
using System.Text;
// Add WCF, WCF Adapter LOB SDK, and Oracle Database adapter namepaces
using System.ServiceModel;
using Microsoft.ServiceModel.Channels;
using Microsoft.Adapters.OracleDB;
// Include this namespace for WCF Adapter LOB SDK and Oracle Database adapter exceptions
using Microsoft.ServiceModel.Channels.Common;
// Alias client namespaces to shorten declarations of "shared" types
using CREATE_ACCOUNTns = microsoft.lobservices.oracledb._2007._03.SCOTT.Package.ACCOUNT_PKG.CREATE_ACCOUNT;
using GET_ACCOUNT_BY_IDns = microsoft.lobservices.oracledb._2007._03.SCOTT.Package.ACCOUNT_PKG.GET_ACCOUNT.overload1;
using GET_ACCOUNT_BY_NAMEns = microsoft.lobservices.oracledb._2007._03.SCOTT.Package.ACCOUNT_PKG.GET_ACCOUNT.overload2;
// This sample demonstrates calling overloaded packaged procedures on Oracle
// First a new account is created by calling CREATE_ACCOUNT which takes two record parameters
// Then the information for the new account is returned by calling an overloaded procedure GET_ACCOUNT
// The first overload returns the account information by account ID
// The second overload returns the account information by account name
// Notice that different clients (and namespaces) are created for overloaded procedures and functions
namespace OracleOverloadsSM
{
class Program
{
static void Main(string[] args)
{
decimal acctId;
string newAccountName = "Paula Bento";
Console.WriteLine("Creating clients");
// Create Client for CREATE_ACCOUNT Function
SCOTTPackageACCOUNT_PKGClient createAccountClient =
new SCOTTPackageACCOUNT_PKGClient("OracleDBBinding_SCOTT.Package.ACCOUNT_PKG");
// NOTE: user name and password are case-sensitive
createAccountClient.ClientCredentials.UserName.UserName = "SCOTT";
createAccountClient.ClientCredentials.UserName.Password = "TIGER";
// Create Client for GET_ACCOUNT Overload 1 -- takes ACCOUNT ID parameter
SCOTTPackageACCOUNT_PKGGET_ACCOUNToverload1Client getAccountByIdClient =
new SCOTTPackageACCOUNT_PKGGET_ACCOUNToverload1Client("OracleDBBinding_SCOTT.Package.ACCOUNT_PKG.GET_ACCOUNT.overload1");
// NOTE: user name and password are case-sensitive
getAccountByIdClient.ClientCredentials.UserName.UserName = "SCOTT";
getAccountByIdClient.ClientCredentials.UserName.Password = "TIGER";
// Create Client for GET_ACCOUNT Overload 2 -- takes ACCOUNT NAME parameter
// NOTE: this client can be created from configuration; detail provided here
// for demonstration
OracleDBBinding overload2Binding = new OracleDBBinding();
EndpointAddress overload2EndpointAddress = new EndpointAddress("oracleDB://ADAPTER");
SCOTTPackageACCOUNT_PKGGET_ACCOUNToverload2Client getAccountByNameClient =
new SCOTTPackageACCOUNT_PKGGET_ACCOUNToverload2Client(overload2Binding, overload2EndpointAddress);
// NOTE: user name and password are case-sensitive
getAccountByNameClient.ClientCredentials.UserName.UserName = "SCOTT";
getAccountByNameClient.ClientCredentials.UserName.Password = "TIGER";
try
{
Console.WriteLine("Opening clients -- please wait");
// Open clients
createAccountClient.Open();
getAccountByIdClient.Open();
getAccountByNameClient.Open();
Console.WriteLine("Creating new account");
// Create an account record
// NOTE: ACCTRECORD is defined in all three namespaces so specify the definition
// that corresponds to the client.
CREATE_ACCOUNTns.ACCTRECORD acctRec = new CREATE_ACCOUNTns.ACCTRECORD();
// Set any value for ACCTID -- new account ID is returned by CREATE_ACCOUNT
acctRec.ACCTID = 0;
acctRec.NAME = newAccountName;
acctRec.BALANCE = 10537;
// Create address record
CREATE_ACCOUNTns.ACCOUNT_PKGADDRESS_REC_TYPERECORD addrRec = new CREATE_ACCOUNTns.ACCOUNT_PKGADDRESS_REC_TYPERECORD();
addrRec.STREET = "456 Valley Rd";
addrRec.CITY = "New York";
addrRec.STATE = "NY";
// Create account
acctId = (decimal)createAccountClient.CREATE_ACCOUNT(acctRec, addrRec);
Console.WriteLine("New Account Created: AccountId = {0}, Name = {1}, Balance = {2:C}",
acctId, acctRec.NAME, acctRec.BALANCE);
/* Get new account by Id */
GET_ACCOUNT_BY_IDns.ACCTRECORD acctById = getAccountByIdClient.GET_ACCOUNT(acctId);
Console.WriteLine("Account Returned by Id: AccountId={0}, Name={1}, Balance={2:C}",
acctById.ACCTID, acctById.NAME, acctById.BALANCE);
/* Get new account by Name */
GET_ACCOUNT_BY_NAMEns.ACCTRECORD acctByName = getAccountByNameClient.GET_ACCOUNT(newAccountName);
Console.WriteLine("Account Returned by Name: AccountId={0}, Name={1}, Balance={2:C}",
acctByName.ACCTID, acctByName.NAME, acctByName.BALANCE);
Console.WriteLine("Hit <RETURN> to finish");
Console.ReadLine();
}
catch (TargetSystemException tex)
{
Console.WriteLine("Exception occurred on the Oracle Database");
Console.WriteLine(tex.InnerException.Message);
}
catch (ConnectionException cex)
{
Console.WriteLine("Exception occurred connecting to the Oracle Database");
Console.WriteLine(cex.InnerException.Message);
}
catch (Exception ex)
{
Console.WriteLine("Exception is: " + ex.Message);
if (ex.InnerException != null)
{
Console.WriteLine("Inner Exception is: " + ex.InnerException.Message);
}
throw ex;
}
finally
{
// Close all the clients
createAccountClient.Close();
getAccountByIdClient.Close();
getAccountByNameClient.Close();
}
}
}
}