SAP アダプターに対する操作を呼び出すには、 IRequestChannel または IOutputChannel チャネル図形を使用して、アダプターにメッセージを送信します。 基本的なパターンは、バインド (SAPBinding) と接続 URI から作成されたエンドポイントを使用して、必要なチャネル図形のチャネル ファクトリを作成することです。 次に、ターゲット操作の メッセージ スキーマに準拠する SOAP メッセージを表す Message インスタンスを作成します。 その後、チャネル ファクトリから作成されたチャネルを使用して、この メッセージ を SAP アダプターに送信できます。 IRequestChannel を使用している場合は、応答を受け取ります。 SAP システムでの操作の実行に問題がある場合、SAP アダプターは Microsoft.ServiceModel.Channels.Common.TargetSystemException をスローします。
WCF で IRequestChannel を使用して操作を送信する方法の概要については、「 クライアント Channel-Level プログラミング」を参照してください。
このトピックのセクションでは、WCF チャネル モデルを使用して SAP アダプターに対する操作を呼び出すのに役立つ情報を提供します。
WCF チャネル モデルでの BAPI トランザクションのサポート
同じ SAP 接続を使用して呼び出されるすべての BAPI は、SAP システム上の同じ作業論理ユニット (LUW) またはトランザクションの一部です。 各 WCF チャネルは、SAP システムへの一意の接続を表します。 WCF チャネル モデルを使用して BAPI トランザクションをサポートするには:
LUW (トランザクション) 内のすべての BAPI が同じチャネル経由で送信されていることを確認します。 これには、BAPI_TRANSACTION COMMIT またはBAPI_TRANSACTION_ROLLBACK操作が含まれます。
チャネルで次の BAPI を呼び出す前に、BAPI に対して受信した応答メッセージをすべて閉じてください。 (これはすべての操作に対して行う必要がありますが、BAPI では特に重要です)。
BAPI トランザクションの詳細については、 SAP での BAPI に対する操作を参照してください。
SAP アダプターへのフラット ファイル IDOC のストリーミング
SendIdoc 操作を使用して、フラット ファイル (文字列) IDOC をアダプターに送信します。 IDOC データは、この操作の単一ノードの下の文字列として表されます。 このため、SAP アダプターは、要求メッセージでのノード値ストリーミングをサポートします。 ノード値ストリーミングを実行するには、IDOC データをストリーミングできる System.ServiceModel.Channels.BodyWriter を使用して、SendIdoc 操作の要求メッセージを作成する必要があります。 これを行う方法の詳細については、「 WCF チャネル モデルを使用した SAP Flat-File IDOC のストリーミング」を参照してください。
チャネルを使用して操作を呼び出す方法
IRequestChannel を使用して操作を呼び出すには、次の手順を実行します。
IRequestChannel のインスタンスを使用して操作を呼び出す方法
チャネル ファクトリ (ChannelFactory<IRequestChannel>) を構築します。 これを行うには、バインド (SAPBinding) とエンドポイント アドレスを指定する必要があります。 バインドとエンドポイント アドレスは、コード内で命令型に指定することも、構成で宣言によって指定することもできます。 ファクトリを開く前に送信する操作に必要なバインディング プロパティを設定する必要があります。 構成でバインディングとエンドポイント アドレスを指定する方法の詳細については、「SAP を 使用してチャネルを作成する」を参照してください。
// Create a binding SAPBinding binding = new SAPBinding(); // Create an endpoint address by using the connection URI EndpointAddress endpointAddress = new EndpointAddress("sap://Client=800;lang=EN@A/YourSAPHost/00"); // Create the channel factory ChannelFactory<IRequestChannel> factory = new ChannelFactory<IRequestChannel>(binding, address);
ClientCredentials プロパティを使用して、チャネル ファクトリのユーザー名パスワード資格情報を設定します。
factory.Credentials.UserName.UserName = "YourUserName"; factory.Credentials.UserName.Password = "YourPassword";
チャンネルファクトリーを開きます。
factory.Open();
ファクトリからチャネルを取得して開きます。
IRequestChannel channel = factory.CreateChannel(); channel.Open();
ターゲット操作の メッセージ インスタンスを作成します。 ターゲット操作のメッセージ アクションが指定されていることを確認します。 この例では、文字列に XmlReader を作成することで、メッセージ本文が渡されます。 ターゲット操作は、SAP システムで SD_RFC_CUSTOMER_GET RFC を呼び出します。
string inputXml = "\<SD_RFC_CUSTOMER_GET xmlns="http://Microsoft.LobServices.Sap/2007/03/Rfc/\"> <KUNNR i:nil=\"true\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"> </KUNNR> <NAME1>AB*</NAME1> <CUSTOMER_T> </CUSTOMER_T> </SD_RFC_CUSTOMER_GET>"; //create an XML reader from the input XML XmlReader reader = XmlReader.Create(new MemoryStream(Encoding.Default.GetBytes(inputXml))); //create a WCF message from our XML reader Message inputMessge = Message.CreateMessage(MessageVersion.Soap11, "http://Microsoft.LobServices.Sap/2007/03/Rfc/SD_RFC_CUSTOMER_GET", reader);
チャネルで Request メソッドを呼び出して、SAP アダプターにメッセージを送信し、応答を受信します。 SAP システムで例外が発生した場合、アダプターは TargetSystemException をスローします。 (SAP 以外の例外の場合は、その他の例外が発生する可能性があります)。SAP エラーの説明は、TargetSystemException の InnerException.Message プロパティから取得できます。
try { Message messageOut = channel.Request(messageIn); } catch (Exception ex) { // handle exception }
応答を処理します。 この例では、 GetReaderAtBodyContents が応答メッセージに対して呼び出され、メッセージ本文が取得されます。
XmlReader readerOut = messageOut.GetReaderAtBodyContents();
応答メッセージの処理が完了したら、リーダーとメッセージを閉じます。
readerOut.Close(); messageOut.Close();
チャネルとチャネル ファクトリの使用が完了したら、それらを閉じます。 ファクトリを閉じると、ファクトリで作成されたすべてのチャネルが閉じられます。
channel.Close() factory.Close();
次を除き、 IOutputChannel 図形を使用してメッセージを送信する場合も同じ手順に従います。
手順 1 で ChannelFactory<IOutputChannel> を作成します。
手順 6 でチャネルで Send メソッドを呼び出します。
channel.Send(messageIn);
。IOutputChannel に対して返される応答メッセージはありません。
例
次の例は、 IRequestChannel チャネルを使用して RFC を呼び出す方法を示しています。 この例では、SD_RFC_CUSTOMER_GET RFC を呼び出して、名前が "AB" で始まる顧客の一覧を取得します。 応答メッセージは XmlReader を使用して使用され、返された各顧客の顧客番号と名前がコンソールに書き込まれます。
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using System.ServiceModel;
using Microsoft.Adapters.SAP;
using Microsoft.ServiceModel.Channels;
using System.ServiceModel.Channels;
namespace SapRfcClientCM
{
class Program
{
static void Main(string[] args)
{
//create a binding
SAPBinding binding = new SAPBinding();
//set up an endpoint address.
EndpointAddress endpointAddress = new EndpointAddress("sap://Client=800;lang=EN@A/YourSAPHost/00");
//create a channel factory, capable of sending a request to SAP and receiving a reply (IRequestChannel)
ChannelFactory<IRequestChannel> factory = new ChannelFactory<IRequestChannel>(binding, endpointAddress);
// add credentials
factory.Credentials.UserName.UserName = "YourUserName";
factory.Credentials.UserName.Password = "YourPassword";
//open the factory
factory.Open();
//obtain a channel from the factory by specifying the address you want to connect to
IRequestChannel channel = factory.CreateChannel();
//open the channel
channel.Open();
//create an XML message to send to the SAP system
//We are invoking the SD_RFC_CUSTOMER_GET RFC.
//The XML below specifies that we want to search for customers with names starting with "AB"
string inputXml = "<SD_RFC_CUSTOMER_GET xmlns=\"http://Microsoft.LobServices.Sap/2007/03/Rfc/\"> <KUNNR i:nil=\"true\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"> </KUNNR> <NAME1>AB*</NAME1> <CUSTOMER_T> </CUSTOMER_T> </SD_RFC_CUSTOMER_GET>";
//create an XML reader from the input XML
XmlReader readerOut = XmlReader.Create(new MemoryStream(Encoding.Default.GetBytes(inputXml)));
//create a WCF message from the XML reader
Message messageOut = Message.CreateMessage(MessageVersion.Default, "http://Microsoft.LobServices.Sap/2007/03/Rfc/SD_RFC_CUSTOMER_GET", readerOut);
//send the message to SAP and obtain a reply
Message messageIn = channel.Request(messageOut);
// Write the KUNNR and NAME1 fields for each returned record to the Console
Console.WriteLine("Results of SD_RFC_CUSTOMER_GET");
Console.WriteLine("KUNNR\t\tNAME1");
XmlReader readerIn = messageIn.GetReaderAtBodyContents();
while (readerIn.Read())
{
if (readerIn.IsStartElement())
{
switch (readerIn.Name)
{
case "RFCCUST":
Console.Write("\n");
break;
case "KUNNR":
readerIn.Read();
Console.Write(readerIn.ReadString() + "\t");
break;
case "NAME1":
readerIn.Read();
Console.Write(readerIn.ReadString() + "\t");
break;
default:
break;
}
}
}
// return the cursor
Console.WriteLine();
// Close the input reader
readerIn.Close();
// Close the input message. You should do this for every message you
// send on the channel
messageIn.Close();
// close the channel when you are done using it.
channel.Close();
//close the factory
//note: closing the factory will close all of its channels.
factory.Close();
}
}
}