WCF サービス モデルを使用して SAP で BAPI を呼び出す
SAP アダプターは、BAPI を次のように表示します。
RFC 操作。 他の RFC と同様の BAPI は、[アダプター サービス参照の追加] プラグインの [RFC] ノードの下に表示されます。
SAP ビジネス オブジェクトのメソッド。 ビジネス オブジェクトのメソッドとして、BAPI は、アダプター サービス参照プラグインの BAPI ノードの下にあるビジネス オブジェクトによって表示されます。
RFC 操作として BAPI を呼び出す場合でも、ビジネス オブジェクト メソッドとして呼び出す場合でも、各 BAPI は常に SAP システム上の LUW の一部です。
SAP アダプターが BAPI をサポートする方法の概要については、「SAP での BAPI に対する操作」を参照してください。
WCF サービス モデルを使用してビジネス オブジェクト メソッドとして BAPI を呼び出すと、各 SAP ビジネス オブジェクトは WCF クライアント クラスによって表され、そのビジネス オブジェクトの BAPI はクライアント上のメソッドとして表されます。 アダプター サービス参照 Visual Studio プラグインを使用して、コードで呼び出す各 BAPI のメソッドを含む特定のビジネス オブジェクトの WCF クライアント クラスを生成できます。 アダプター サービス参照の追加プラグインでは、各 BAPI で使用されるパラメーターとデータ型をカプセル化する .NET 型も生成されます。 その後、この WCF クライアント クラスのインスタンスを作成し、そのメソッドを呼び出してターゲット BAPI を呼び出すことができます。
次のセクションでは、ビジネス オブジェクトのメソッドとして BAPI を呼び出す方法と、WCF サービス モデルで BAPI トランザクションがどのようにサポートされるかについて説明します。
WCF クライアント クラス
SAP アダプターは、ビジネス オブジェクトごとに異なるサービス コントラクトを表示します。 つまり、ビジネス オブジェクトごとに一意の WCF クライアント クラスが作成されます。 このクラスの名前は、ビジネス オブジェクトの種類に基づいています。 たとえば、Sales Order ビジネス オブジェクト (ビジネス オブジェクトの種類BUS2032) の場合、WCF クライアント クラスは BapiBUS2032Client です。 ビジネス オブジェクト内の各ターゲット BAPI は、生成された WCF クライアント クラスのメソッドとして表されます。 各メソッドでは、次の手順を実行します。
SAP エクスポート パラメーターが 出力 パラメーターとして表示される
SAP 呼び出しパラメーターは ref パラメーターとして表示されます。
構造などの複雑な SAP 型は、SAP 型のフィールドに対応するプロパティを持つ .NET クラスとして表示されます。 これらのクラスは、次の名前空間で定義されています: microsoft.lobservices.sap._2007._03.Types.Rfc。
ビジネス オブジェクトごとにBAPI_TRANSACTION_COMMITとBAPI_TRANSACTION_ROLLBACKが表示されるため、常に WCF クライアントに含める必要があります。
次のコードは、Sales Order ビジネス オブジェクト用に生成された WCF クライアント クラスの一部を示しています。 このクライアントには、CREATEFROMDAT2、BAPI_TRANSACTION_COMMIT、BAPI_TRANSACTION_ROLLBACKを呼び出すメソッドが含まれています。 わかりやすくするために、コンストラクターとその他のコードは省略されています。
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public partial class BapiBUS2032Client : System.ServiceModel.ClientBase<BapiBUS2032>, BapiBUS2032 {
// Code has been removed for clarity
/// <summary>The Metadata for this RFC was generated using the RFC SDK.</summary>
/// <param name="SALESDOCUMENT">Number of Generated Document</param>
/// <param name="BEHAVE_WHEN_ERROR">Error Handling</param>
/// …
/// <param name="ORDER_TEXT">Texts</param>
/// <param name="PARTNERADDRESSES">BAPI Reference Structure for Addresses (Org./Company)</param>
/// <param name="RETURN">Return Messages</param>
/// <returns></returns>
public string CREATEFROMDAT2(
string BEHAVE_WHEN_ERROR,
string BINARY_RELATIONSHIPTYPE,
string CONVERT,
string INT_NUMBER_ASSIGNMENT,
microsoft.lobservices.sap._2007._03.Types.Rfc.BAPISDLS LOGIC_SWITCH,
microsoft.lobservices.sap._2007._03.Types.Rfc.BAPISDHD1 ORDER_HEADER_IN,
microsoft.lobservices.sap._2007._03.Types.Rfc.BAPISDHD1X ORDER_HEADER_INX,
string SALESDOCUMENTIN,
microsoft.lobservices.sap._2007._03.Types.Rfc.BAPI_SENDER SENDER,
string TESTRUN,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPIPAREX[] EXTENSIONIN,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPICCARD[] ORDER_CCARD,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPICUBLB[] ORDER_CFGS_BLOB,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPICUINS[] ORDER_CFGS_INST,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPICUPRT[] ORDER_CFGS_PART_OF,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPICUCFG[] ORDER_CFGS_REF,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPICUREF[] ORDER_CFGS_REFINST,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPICUVAL[] ORDER_CFGS_VALUE,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPICUVK[] ORDER_CFGS_VK,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPICOND[] ORDER_CONDITIONS_IN,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPICONDX[] ORDER_CONDITIONS_INX,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPISDITM[] ORDER_ITEMS_IN,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPISDITMX[] ORDER_ITEMS_INX,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPISDKEY[] ORDER_KEYS,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPIPARNR[] ORDER_PARTNERS,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPISCHDL[] ORDER_SCHEDULES_IN,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPISCHDLX[] ORDER_SCHEDULES_INX,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPISDTEXT[] ORDER_TEXT,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPIADDR1[] PARTNERADDRESSES,
ref microsoft.lobservices.sap._2007._03.Types.Rfc.BAPIRET2[] RETURN) { ...}
/// <summary>The Metadata for this RFC was generated using the RFC SDK.</summary>
/// <param name="RETURN">Confirmations</param>
/// <param name="WAIT">Using the command `COMMIT AND WAIT`</param>
/// <returns></returns>
public microsoft.lobservices.sap._2007._03.Types.Rfc.BAPIRET2 BAPI_TRANSACTION_COMMIT(string WAIT) { ... }
/// <summary>The Metadata for this RFC was generated using the RFC SDK.</summary>
/// <param name="RETURN">Confirmations</param>
/// <returns></returns>
public microsoft.lobservices.sap._2007._03.Types.Rfc.BAPIRET2 BAPI_TRANSACTION_ROLLBACK() { ... }
}
WCF サービス モデルの BAPI トランザクション
すべての BAPI は、RFC として呼び出されるかビジネス オブジェクト メソッドとして呼び出されるかに関係なく、SAP システム上のトランザクション (LUW) の一部です。また、同じ SAP 接続を介して受信されたすべての BAPI は、SAP システム上の同じ BAPI トランザクションの一部です。 SAP は、接続でBAPI_TRANSACTION_COMMITまたはBAPI_TRANSACTION_ROLLBACKを受信すると、BAPI トランザクションをコミットまたはロールバックします。 コミットまたはロールバックが実行されると、接続を介して受信した次の BAPI が新しいトランザクションを開始します。
アダプターの場合、各 WCF チャネルには専用の SAP 接続があります。 WCF サービス モデルでは、各 WCF クライアントには、SAP システムへのメッセージの送信に使用される内部チャネルがあります。 つまり、特定の WCF クライアントを使用して呼び出される BAPI は、SAP システム上の一意の BAPI トランザクションの一部です。 これにより、WCF サービス モデルを使用してビジネス オブジェクト メソッドとして BAPI を呼び出す場合、大きな制限が課されます。 各 SAP ビジネス オブジェクトは専用の WCF クライアント クラスによって表されるため、同じトランザクションの一部として 2 つの異なるビジネス オブジェクトから BAPI を呼び出すことはできません。 これを回避する方法は、RFC 操作として BAPI を呼び出す方法です。 これは、アダプター サービス参照の追加プラグインが RFC 操作用に 1 つの WCF クライアントを生成するため、そのクライアントを使用して呼び出されたすべての操作が同じ WCF チャネル経由で送信されるためです。
重要
異なる SAP ビジネス オブジェクトの BAPI を同じ BAPI トランザクションに含める場合は、(同じ WCF クライアントを使用して) RFC 操作として呼び出す必要があります。 ビジネス オブジェクト メソッドとして呼び出すことはできません。
BAPI_TRANSACTION_COMMITまたはBAPI_TRANSACTION_ROLLBACKを呼び出して、SAP システムで BAPI トランザクションをコミットまたはロールバックします。 アダプターは、次の 2 つの BAPI を表示します。
RFC 操作として [基準] ノードの下。
各ビジネス オブジェクトの下。
アダプターが SAP で BAPI トランザクションをサポートする方法の詳細については、「SAP での BAPI に対する操作」を参照してください。
ビジネス オブジェクトのメソッドとして BAPI を呼び出すアプリケーションを作成する方法
このセクションでは、ビジネス オブジェクトのメソッドとして BAPI を呼び出す方法について説明します。 RFC 操作として BAPI を呼び出すには、同じ基本的な手順に従う必要があります。ただし、RFC 操作として BAPI を対象とする WCF クライアントを作成し、それを使用して各 BAPI を呼び出す点が除きます。
BAPI クライアント アプリケーションを作成するには、次の手順を実行します。
BAPI クライアント アプリケーションを作成するには
WCF クライアント クラスを生成します。 アダプター サービス参照の追加 Visual Studio プラグインまたは ServiceModel メタデータ ユーティリティ ツール (svcutil.exe) を使用して、作業するビジネス オブジェクトと BAPI を対象とする WCF クライアント クラス (またはクラス) を生成します。 ターゲット ビジネス オブジェクトごとに公開されているBAPI_TRANSACTION_COMMITとBAPI_TRANSACTION_ROLLBACK メソッド (BAPI) を必ず含めます。 WCF クライアントを生成する方法の詳細については、「SAP ソリューション成果物の WCF クライアントまたは WCF サービス コントラクトの生成」を参照してください。
手順 1 で生成された WCF クライアント クラスのインスタンスを作成し、WCF クライアントを作成して構成します。 WCF クライアントの構成には、クライアントが使用するバインディングアドレスとエンドポイント アドレスを指定する必要があります。 これは、コード内で命令的に行うか、構成で宣言的に行うことができます。 クライアント バインドを指定する方法の詳細については、「 SAP システムのクライアント バインドの構成」を参照してください。 次のコードでは、構成から Sales Order (BUS2032) SAP ビジネス オブジェクトの WCF クライアントを初期化し、SAP システムの資格情報を設定します。
BapiBUS2032Client bapiClient = new BapiBUS2032Client("SAPBinding_BapiBUS2032"); bapiClient.ClientCredentials.UserName.UserName = "YourUserName"; bapiClient.ClientCredentials.UserName.Password = "YourPassword";
WCF クライアントを開きます。
bapiClient.Open();
手順 2 で作成した WCF クライアントでメソッドを呼び出して、SAP システム上の適切な BAPI を呼び出します。 SAP システムで複数の BAPI を呼び出すことができます。
トランザクションを終了する方法:
BAPI_TRANSACTION_COMMIT メソッドを呼び出してトランザクションをコミットします。
bapiClient.BAPI_TRANSACTION_COMMIT("X");
BAPI_TRANSACTION_ROLLBACK メソッドを呼び出してトランザクションをロールバックします。
bapiClient.BAPI_TRANSACTION_ROLLBACK();
WCF クライアントを終了します。
bapiClient.Close();
例
次の例では、Sales Order ビジネス オブジェクトで CREATEFROMDAT2 BAPI を呼び出します。 BAPI を複数回呼び出し、BAPI_TRANSACTION_COMMITを呼び出してトランザクションをコミットします。 BAPI の呼び出し時にエラーが発生した場合は、例外ハンドラーでBAPI_TRANSACTION_ROLLBACKが呼び出され、トランザクションがロールバックされます。
CREATEFROMDAT2 メソッドは、多くのパラメーターを受け取ります。簡潔にするために、例ではこれらを省略しています。 BAPI トランザクションを示すサンプルについては、Microsoft BizTalk アダプター パックに付属のサンプルを参照してください。 詳細については、「 SAP アダプターのサンプル」を参照してください。
using System;
using System.Collections.Generic;
using System.Text;
// Add WCF, Adapter LOB SDK, and SAP Adapter namepaces
using System.ServiceModel;
using Microsoft.Adapters.SAP;
using Microsoft.ServiceModel.Channels;
// Include this namespace for Adapter LOB SDK and SAP exceptions
using Microsoft.ServiceModel.Channels.Common;
using microsoft.lobservices.sap._2007._03.Types.Rfc;
// This Example demonstrates BAPI transactions. Two sales orders are
// created using the CREATEFROMDAT2 method of a SAP Business Object.
// After the orders are created, the BAPI transaction is committed.
// If an exception occurs when sending the BAPIs, the BAPI transaction is
// rolled back.
//
namespace SapBapiTxClientSM
{
class Program
{
static void Main(string[] args)
{
// Create the BAPI client from the generated endpoint configuration.
BapiBUS2032Client bapiClient = null;
Console.WriteLine("BAPI transaction sample started");
Console.WriteLine("\nCreating business object client");
try
{
bapiClient = new BapiBUS2032Client("SAPBinding_BapiBUS2032");
bapiClient.ClientCredentials.UserName.UserName = "YourUserName";
bapiClient.ClientCredentials.UserName.Password = "YourPassword";
// Open the BAPI Client
bapiClient.Open();
...
// send first BAPI
try
{
string salesDocNumber1 = bapiClient.CREATEFROMDAT2(
...
// parameters ommitted
...
);
}
catch (Exception ex)
{
bapiClient.BAPI_TRANSACTION_ROLLBACK();
throw;
}
...
// send second BAPI
try
{
string salesDocNumber1 = bapiClient.CREATEFROMDAT2(
...
// parameters omitted
...
);
}
catch (Exception ex)
{
bapiClient.BAPI_TRANSACTION_ROLLBACK();
throw;
}
...
// Commit BAPI Transaction
try
{
bapiClient.BAPI_TRANSACTION.Commit();
}
catch (Exception ex)
{
bapiClient.BAPI_TRANSACTION_ROLLBACK();
throw;
}
...
}
catch (ConnectionException cex)
{
// Get here if problem connecting to the SAP system
Console.WriteLine("Exception occurred connecting to the SAP system");
Console.WriteLine(cex.InnerException.Message);
}
catch (TargetSystemException tex)
{
// Get here if the SAP system returns an exception
Console.WriteLine("Exception occurred on the SAP System");
Console.WriteLine(tex.InnerException.Message);
}
catch (Exception ex)
{
Console.WriteLine("Exception is: " + ex.Message);
if (ex.InnerException != null)
{
Console.WriteLine("Inner Exception is: " + ex.InnerException.Message);
}
}
finally
{
// Close the client when finished
if (bapiClient != null)
{
if (bapiClient.State == CommunicationState.Opened)
bapiClient.Close();
else
bapiClient.Abort();
}
}
}
}
}