Why does. net need to call BAPI_TRANSACTION_COMMIT to call SAP's BAPI? First, you must understand the role of the BAPI "BAPI_TRANSACTION_COMMIT. It has a lot of credit. Many bapis in SAP do not have any results for direct calls, because a COMMIT is required to take effect. For example, the BAPI that generates the asset number: BAPI_FIXEDASSET_CREATE1, if you call SE38 directly in SE37 or use SE38 to call it, you can obtain an asset number but query it in AS03. The system will be very idiotic and prompt you: the asset number does not exist in company XX. What's more, when you create an asset number in AS01, the newly created asset number skips the previous BAPI to generate a "failed" number.
In this case, you need to COMMIT the BAPI and then call the BAPI_TRANSACTION_COMMIT. However, this can be done in SE38, while in. net is not that simple. It is not possible to call the BAPI_TRANSACTION_COMMIT directly after the BAPI_FIXEDASSET_CREATE1 is called. Although the asset number is generated, it is still a waste number. It is similar to the call in se37.
To solve this problem in. net, you need to use the RfcSessionManager. BeginContext and RfcSessionManager. EndContext methods. Only bapis can be called between these two methods!
The Code is as follows:
1. First reference: using SAP. Middleware. Connector;
2. Call code:
Public void nco (DataSet ds)
{
IDestinationConfiguration ID = new RfcConfig ();
RfcDestinationManager. RegisterDestinationConfiguration (ID );
RfcDestination prd = RfcDestinationManager. GetDestination ("PRD_000 ");
RfcDestinationManager. UnregisterDestinationConfiguration (ID );
Nco (prd, ds );
}
Public void nco (RfcDestination prd, DataSet ds)
{
Bool asset = false;
// Select the name of the BAPI to be called
RfcFunctionMetadata BAPI_COMPANYCODE_GETDETAIL_MD = prd. Repository. GetFunctionMetadata ("BAPI_REQUISITION_CREATE ");
// Create an "instance" that calls this BAPI"
IRfcFunction function = null;
Function = BAPI_COMPANYCODE_GETDETAIL_MD.CreateFunction ();
IRfcTable ITEMS = function. GetTable ("REQUISITION_ITEMS ");
IRfcTable ACCOUNT = function. GetTable ("REQUISITION_ACCOUNT_ASSIGNMENT ");
IRfcTable RETURN = function. GetTable ("RETURN ");
Int j = 0;
RfcSessionManager. BeginContext (prd); // The BAPI needs to be called at the same time during the period, and each BAPI is sequentially associated, so it is best to use this to enclose
For (int I = 0; I <ds. Tables [0]. Rows. Count; I ++)
{
ITEMS. Insert ();
J = j + 1;
J = j * 10;
ITEMS. CurrentRow. SetValue ("PREQ_ITEM", j. ToString ());
ITEMS. CurrentRow. SetValue ("PREQ_NAME", ds. Tables [0]. Rows [I] ["QGA27"]. ToString ());
ITEMS. CurrentRow. SetValue ("CREATED_BY", ds. Tables [0]. Rows [I] ["QGA27"]. ToString ());
ITEMS. CurrentRow. SetValue ("PREQ_DATE", Convert. ToDateTime (ds. Tables [0]. Rows [I] ["QGA15"]. ToString (). Date );
ITEMS. CurrentRow. SetValue ("MATERIAL", ds. Tables [0]. Rows [I] ["QGA04"]. ToString ());
ITEMS. CurrentRow. SetValue ("SHORT_TEXT", ds. Tables [0]. Rows [I] ["QGA05"]. ToString ());
ITEMS. CurrentRow. SetValue ("PLANT", "1201 ");
ITEMS. CurrentRow. SetValue ("QUANTITY", Convert. ToDecimal (ds. Tables [0]. Rows [I] ["QGA07"]. ToString ()));
ITEMS. CurrentRow. SetValue ("DELIV_DATE", Convert. ToDateTime (ds. Tables [0]. Rows [I] ["QGA09"]. ToString (). Date );
ITEMS. CurrentRow. SetValue ("C_AMT_BAPI", Convert. ToDecimal (ds. Tables [0]. Rows [I] ["QGA14"]. ToString ()));
ITEMS. CurrentRow. SetValue ("ACCTASSCAT", ds. Tables [0]. Rows [I] ["QGA12"]. ToString ());
ITEMS. CurrentRow. SetValue ("DOC_TYPE", ds. Tables [0]. Rows [I] ["QGA28"]. ToString ());
ITEMS. CurrentRow. SetValue ("UNIT", ds. Tables [0]. Rows [I] ["QGA06"]. ToString ());
ACCOUNT. Insert ();
ACCOUNT. CurrentRow. SetValue ("PREQ_ITEM", j. ToString ());
ACCOUNT. CurrentRow. SetValue ("COST_CTR", ds. Tables [0]. Rows [I] ["QGA31"]. ToString ());
ACCOUNT. CurrentRow. SetValue ("ORDER_NO", ds. Tables [0]. Rows [I] ["QGA10"]. ToString ());
If (ds. tables [0]. rows [I] ["QGA12"]. toString (). trim () = "A") // If the category is A, that is, the asset ID is required.
{
ACCOUNT. CurrentRow. SetValue ("ASSET_NO", GetASSET (prd, I, ds); // you can specify the ID of the newly created asset.
ACCOUNT. CurrentRow. SetValue ("CO_AREA", "1000 ");
ACCOUNT. CurrentRow. SetValue ("SUB_NUMBER", "0000 ");
}
}
Function. SetValue ("REQUISITION_ITEMS", ITEMS );
Function. SetValue ("REQUISITION_ACCOUNT_ASSIGNMENT", ACCOUNT );
Function. Invoke (prd); // submit a call to BAPI
RfcSessionManager. EndContext (prd );
If (RETURN. GetString ("TYPE"). ToString (). Trim () = "I ")
{
Suess. Text = RETURN. GetString ("MESSAGE"). ToString ();
BANFN. Text = "returned requisition NUMBER:" + function. GetString ("NUMBER"). Trim ();
}
Else if (RETURN. GetString ("TYPE"). ToString (). Trim () = "E ")
{
Error. Text = RETURN. GetString ("MESSAGE"). ToString ();
}
Prd = null;
}
/// <Summary>
/// Obtain the asset ID
/// </Summary>
/// <Param name = "prd"> </param>
/// <Returns> </returns>
Public string GetASSET (RfcDestination prd, int I, DataSet ds)
{
RfcFunctionMetadata BAPI_COMPANYCODE_GETDETAIL_MD = prd. Repository. GetFunctionMetadata ("BAPI_FIXEDASSET_CREATE1 ");
IRfcFunction function = null;
Function = BAPI_COMPANYCODE_GETDETAIL_MD.CreateFunction ();
Fcirstructure KEY = function. GetStructure ("KEY ");
KEY. SetValue ("COMPANYCODE", "2012 ");
IRfcStructure GENERALDATA = function. GetStructure ("GENERALDATA ");
GENERALDATA. SetValue ("ASSETCLASS", "00005990 ");
GENERALDATA. SetValue ("DESCRIPT", ds. Tables [0]. Rows [I] ["QGA05"]. ToString ());
IRfcStructure GENERALDATAX = function. GetStructure ("GENERALDATAX ");
GENERALDATAX. SetValue ("ASSETCLASS", "X ");
GENERALDATAX. SetValue ("DESCRIPT", "X ");
Function. SetValue ("KEY", KEY );
Function. SetValue ("GENERALDATA", GENERALDATA );
Function. SetValue ("GENERALDATAX", GENERALDATAX );
Prd. Repository. ClearFunctionMetadata (); // it seems that this sentence can be omitted...
RfcFunctionMetadata BAPI_COMPANYCODE_GETDETAIL_MD1 = prd. Repository. GetFunctionMetadata ("BAPI_TRANSACTION_COMMIT ");
IRfcFunction function1 = null;
Function1 = BAPI_COMPANYCODE_GETDETAIL_MD1.CreateFunction ();
Function1.SetValue ("WAIT", "X ");
RfcSessionManager. BeginContext (prd );
Function. Invoke (prd); // submit the API call BAPI_FIXEDASSET_CREATE1 to generate an asset number.
Function1.Invoke (prd); // submit the command to call BAPI_TRANSACTION_COMMIT for COMMIT.
RfcSessionManager. EndContext (prd );
TwMsgbox. AjaxAlert (function. GetValue ("ASSET"). ToString (). Trim ());
Return function. GetValue ("ASSET"). ToString (). Trim ();
}
After the new purchase order is created, everything is OK. At the same time, the created asset number can be recognized in AS03 !!