共用方式為


使用 WCF 服務模型叫用 Oracle 資料庫中的函式和程式

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 用戶端叫用函式或程式,請執行下列步驟。

  1. 產生目標函式、程式或封裝的 WCF 用戶端類別。 這個類別應該包含您要在目標成品上叫用之作業的方法。

    備註

    在 [新增配接器服務參考 Visual Studio 外掛程式] 中,多載函式和程式會出現在 [可用類別和作業 ] 方塊中,顯示為 [NAME].1、[NAME].2、[NAME].3 等等,其中 [NAME] 是多載成品的名稱,而數值是 Oracle 資料庫上的多載標識符。

  2. 建立 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();  
            }  
  
        }  
    }  
}  

另請參閱

使用 WCF 服務模型開發 Oracle 資料庫應用程式