WCF 서비스 모델을 사용하여 SAP에서 BAPI 호출
SAP 어댑터는 다음과 같이 BAPI를 표시합니다.
RFC 작업. 다른 RFC와 같은 BAPI는 어댑터 서비스 추가 참조 플러그 인의 RFC 노드 아래에 표시됩니다.
SAP 비즈니스 개체의 메서드입니다. 비즈니스 개체의 메서드인 BAPI는 어댑터 서비스 참조 추가 플러그 인의 BAPI 노드 아래에 비즈니스 개체에 의해 표시됩니다.
BAPI를 RFC 작업으로 호출하든 비즈니스 개체 메서드로 호출하든, 각 BAPI는 항상 SAP 시스템의 LUW에 속합니다.
SAP 어댑터가 BAPI를 지원하는 방법에 대한 개요는 SAP의 BAPI에 대한 작업을 참조하세요.
WCF 서비스 모델을 사용하여 BAPI를 비즈니스 개체 메서드로 호출하는 경우 각 SAP 비즈니스 개체는 WCF 클라이언트 클래스로 표시되고 해당 비즈니스 개체의 BAPI는 클라이언트에서 메서드로 표시됩니다. 어댑터 서비스 참조 Visual Studio 플러그 인 추가를 사용하여 코드에서 호출하려는 각 BAPI에 대한 메서드를 포함하는 특정 비즈니스 개체에 대한 WCF 클라이언트 클래스를 생성할 수 있습니다. 어댑터 서비스 참조 추가 플러그 인은 각 BAPI에서 사용되는 매개 변수 및 데이터 형식을 캡슐화하는 .NET 형식도 생성합니다. 그런 다음 이 WCF 클라이언트 클래스의 instance 만들고 해당 메서드를 호출하여 대상 BAPI를 호출할 수 있습니다.
다음 섹션에서는 비즈니스 개체의 메서드로 BAPI를 호출하고 WCF 서비스 모델에서 BAPI 트랜잭션을 지원하는 방법을 설명합니다.
WCF 클라이언트 클래스
SAP 어댑터는 각 비즈니스 개체에 대해 다른 서비스 계약을 표시합니다. 즉, 각 비즈니스 개체에 대해 고유한 WCF 클라이언트 클래스가 만들어집니다. 이 클래스의 이름은 비즈니스 개체 형식을 기반으로 합니다. 예를 들어 Sales Order 비즈니스 개체(비즈니스 개체 유형 BUS2032)의 경우 WCF 클라이언트 클래스는 BapiBUS2032Client입니다. 비즈니스 개체의 각 대상 BAPI는 생성된 WCF 클라이언트 클래스의 메서드로 표시됩니다. 각 메서드에서:
SAP 내보내기 매개 변수는 out 매개 변수로 표시됩니다.
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 트랜잭션
RFC 또는 비즈니스 개체 메서드로 호출되는 모든 BAPI는 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 클라이언트 클래스로 표현되므로 동일한 트랜잭션의 일부로 서로 다른 두 비즈니스 개체에서 BAPI를 호출할 수 없습니다. 이를 해결하는 방법은 BAPI를 RFC 작업으로 호출하는 것입니다. 어댑터 서비스 참조 플러그 인 추가는 RFC 작업에 대한 단일 WCF 클라이언트를 생성하므로 해당 클라이언트를 사용하여 호출된 모든 작업이 동일한 WCF 채널을 통해 전송되기 때문입니다.
중요
동일한 BAPI 트랜잭션에 다른 SAP 비즈니스 개체의 BAPI를 포함하려면 동일한 WCF 클라이언트를 사용하여 RFC 작업으로 호출해야 합니다. 비즈니스 개체 메서드로 호출할 수 없습니다.
BAPI_TRANSACTION_COMMIT 또는 BAPI_TRANSACTION_ROLLBACK 호출하여 SAP 시스템에서 BAPI 트랜잭션을 커밋하거나 롤백합니다. 어댑터는 다음과 같은 두 개의 BAPI를 표시합니다.
RFC 작업으로 기본 노드 아래에 있습니다.
각 비즈니스 개체 아래에 있습니다.
어댑터가 SAP에서 BAPI 트랜잭션을 지원하는 방법에 대한 자세한 내용은 SAP의 BAPI에 대한 작업을 참조하세요.
BAPI를 비즈니스 개체의 메서드로 호출하는 애플리케이션을 만드는 방법
이 섹션에서는 비즈니스 개체의 메서드로 BAPI를 호출하는 방법에 대한 정보를 제공합니다. BAPI를 RFC 작업으로 대상으로 하는 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 클라이언트 클래스의 instance 만들고 WCF 클라이언트를 만들고 구성합니다. WCF 클라이언트를 구성하려면 클라이언트에서 사용할 바인딩 및 엔드포인트 주소를 지정해야 합니다. 코드에서 명령적으로 또는 구성에서 선언적으로 이 작업을 수행할 수 있습니다. 클라이언트 바인딩을 지정하는 방법에 대한 자세한 내용은 SAP 시스템에 대한 클라이언트 바인딩 구성을 참조하세요. 다음 코드는 구성에서 SAP 비즈니스 개체의 판매 주문(BUS2032)에 대한 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 메서드는 많은 매개 변수를 사용합니다. 간결함을 위해 예제에서 생략됩니다. Microsoft BizTalk 어댑터 팩과 함께 제공되는 샘플에서 BAPI 트랜잭션을 보여 주는 샘플을 찾을 수 있습니다. 자세한 내용은 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();
}
}
}
}
}