共用方式為


使用 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 Artifact 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 資料庫配接器代表 Oracle RECORD 類型參數和傳回值,以及 REF CURSOR 參數所傳回的結果集,做為包含 Oracle 記錄之資料列資料 (或欄位) 的複雜 XML 類型。 在 WCF 服務模型中,每個 XML 類型都會以 .NET 類別表示;類別的屬性代表 RECORD 類型或 REF CURSOR 結果集的欄位。 Oracle RECORD 類型一律以強型別 .NET 類別表示。 不過,REF CURSOR 結果集可以表示為強型別或弱型別記錄,根據 REF CURSOR 本身是否宣告為強型別或弱型別。 代表 REF CURSOR 或 RECORD 類型參數的類別 (或傳回值,) 是根據程式、函式或封裝,在唯一命名空間中產生。 下表顯示這些命名空間。

Oracle Artifact 命名空間 範例
程序 [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 參數會分割成輸入字串,而輸出 (輸出) 記錄集。 這是因為 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 資料庫配接器支援多載程式、函式和套件,方法是將唯一字串附加至節點識別碼,以及它針對每個多載成品呈現的命名空間。 此字串是第一個多載的 「多載1」、下一個多載的 「overload2」 等等。

在 WCF 服務模型中,每個多載程式或函式都是由唯一的 WCF 用戶端表示。 這與非多載案例不同,其中 SCHEMA 中的所有函式、SCHEMA 中的所有程式,或 PACKAGE 中的所有程式和函式都會由相同的 WCF 用戶端叫用。 下表顯示針對多載程式、函式和封裝產生的 WCF 用戶端名稱和方法。

Oracle Artifact 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 Artifact 命名空間 範例
套件 (程式) [BASE_NS]。 [SCHEMA]。包。[PACKAGE_NAME]。[PROC_NAME][OVERLOAD_ID] microsoft.lobservices.oracledb._2007._03.SCOTT。Package.MYPACKAGE.MYPROC.overload1
套件 (函式) [BASE_NS]。 [SCHEMA]。包。[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 資料庫所維護成品的多載識別碼。

下列範例顯示針對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 資料庫應用程式