WCF チャネル モデルを使用した SAP システムでの操作の呼び出し
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 に対する操作」を参照してください。
フラット ファイル IDOC を SAP アダプターにストリーミングする
SendIdoc 操作を使用して、フラット ファイル (文字列) IDOC をアダプターに送信します。 IDOC データは、この操作で 1 つのノードの下の文字列として表されます。 このため、SAP アダプターは要求メッセージでノード値ストリーミングをサポートしています。 ノード値ストリーミングを実行するには、IDOC データをストリーミングできる System.ServiceModel.Channels.BodyWriter を使用して、SendIdoc 操作の要求メッセージを作成する必要があります。 これを行う方法については、「 WCF チャネル モデルを使用して SAP で IDOC を Flat-File ストリーミングする」を参照してください。
チャネルを使用して操作を呼び出す方法
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();
ターゲット操作の Message インスタンスを作成します。 ターゲット操作のメッセージ アクションが指定されていることを確認します。 この例では、文字列の上に 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();
}
}
}