SAP ABAP BAPI_TRANSACTION_COMMIT的使用方法

为什么.net调用SAP的BAPI接口需要调用BAPI_TRANSACTION_COMMIT呢?首先得明白BAPI_TRANSACTION_COMMIT这个BAPI的作用。它功劳很大,在SAP里面很多的BAPI直接调用是不会有结果的,因为需要COMMIT一下才能生效,比如生成资产编号的BAPI:BAPI_FIXEDASSET_CREATE1,如果对他直接在SE37中调用运行或者使用SE38调用它,虽然可以得到一个资产编号,但是在AS03里面查询,系统会很白痴得提示你:该资产编号不存在于XX公司。更搞的是当你在AS01中新建资产编号时,新建的资产编号会跳过之前用BAPI生成“失败”的号码。

那么,这就需要COMMIT一下,在调用这个BAPI之后再紧接调用BAPI_TRANSACTION_COMMIT这个。但是,在SE38中是可以这样做,而在.net中就没那么简单了,直接在调用完BAPI_FIXEDASSET_CREATE1之后再紧接调用BAPI_TRANSACTION_COMMIT是不可以的,虽然还是生成了资产编号,但仍旧是个废号。跟在SE37中调用无异。

怎么在.net中解决这个问题呢,这就需要用到RfcSessionManager.BeginContext和RfcSessionManager.EndContext这两个方法了。只有在这两个方法之间调用BAPI才能方保万无一失!

代码如下:

1、首先引用:using SAP.Middleware.Connector;

2、调用代码:

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;
//选择要调用的BAPI的名称
RfcFunctionMetadata BAPI_COMPANYCODE_GETDETAIL_MD = prd.Repository.GetFunctionMetadata("BAPI_REQUISITION_CREATE");
//新建调用该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); //因期间需要同一个时间调用BAPI,而且各个BAPI之间有顺序关联,所以最好用这个包围起来
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") //如果类别是A,即资产,则需要资产编号
{
ACCOUNT.CurrentRow.SetValue("ASSET_NO", GetASSET(prd, i, ds)); //设置新建的资产编号
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);//提交调用BAPI
RfcSessionManager.EndContext(prd);
if (RETURN.GetString("TYPE").ToString().Trim() == "I")
{
Suess.Text = RETURN.GetString("MESSAGE").ToString();
BANFN.Text = "返回的请购单号:" + function.GetString("NUMBER").Trim();
}
else if (RETURN.GetString("TYPE").ToString().Trim() == "E")
{
Error.Text = RETURN.GetString("MESSAGE").ToString();
}
prd = null;
}
/// <summary>
/// 取得资产编号
/// </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();
IRfcStructure 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(); //貌似这句可以省略...
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); //提交调用BAPI_FIXEDASSET_CREATE1 生成资产编号
function1.Invoke(prd); //提交调用BAPI_TRANSACTION_COMMIT 进行COMMIT一下
RfcSessionManager.EndContext(prd);
twMsgbox.AjaxAlert(function.GetValue("ASSET").ToString().Trim());
return function.GetValue("ASSET").ToString().Trim();
}

新建立之后的请购单一切OK,同时,建立的资产编号在AS03已经可以认出来了!!

### 解决方案分析 在 SAP ABAP 中调用 `BAPI_TRANSACTION_COMMIT` 并附加参数 `WAIT` 可能会引发后续 BAPI 调用失败的情况。这种现象通常与事务一致性、锁机制以及数据库提交行为有关。 #### 原因分析 当使用 `BAPI_TRANSACTION_COMMIT WAIT` 时,系统会在当前工作单元完成后释放所有内部锁定并等待外部确认完成。如果在此过程中发生异常或超时,可能导致以下问题: - 数据库连接状态被破坏,影响后续 BAPI 的正常执行[^1]。 - 锁定资源未能完全释放,导致其他并发请求冲突[^3]。 - 如果前序 BAPI 执行存在部分错误数据未清理干净,在提交后可能遗留脏数据,干扰后续逻辑运行[^2]。 #### 技术实现中的注意事项 为了规避上述风险,建议采取如下措施: 1. **检查前置条件** 在调用任何 BAPI 之前,务必验证输入参数的有效性和业务规则的一致性。例如对于会计凭证创建场景下的 `BAPI_ACC_DOCUMENT_POST` 和其配套校验函数模块 `BAPI_ACC_DOCUMENT_CHECK` 应先单独测试通过后再继续下一步操作。 2. **合理设置 COMMIT 参数** 使用 `BAPI_TRANSACTION_COMMIT` 时可考虑去掉默认的 `WAIT` 设置或者调整时间间隔至更短周期 (如 `WAIT UP TO 5 SECONDS`) 来减少潜在阻塞可能性: ```abap CALL FUNCTION 'BAPI_TRANSACTION_COMMIT' EXPORTING wait = abap_true. ``` 3. **引入回滚机制** 当检测到某个环节出现问题无法恢复时立即触发 ROLLBACK 动作从而保护整体流程不受单点故障拖累: ```abap IF error_occurred IS INITIAL. CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'. ELSE. PERFORM rollback_logic. ENDIF. ``` 4. **优化调试环境配置** 对于仅在特定环境下表现正常的状况(比如 Debug 下可行而实际部署却不行),需重点排查是否存在隐含依赖关系或是权限不足等问题,并适当增加日志记录便于定位具体位置. 综上所述, 结合以上方法能够有效缓解由于不当应用 `BAPI_TRANSACTION_COMMIT WAIT` 引起的各种兼容性难题. ```abap DATA: lv_return TYPE bapiret2. CALL FUNCTION 'BAPI_ACC_DOCUMENT_POST' TABLES return = lt_return. CHECK NOT lines( lt_return ) > 0 OR lt_return[]-type NE 'E'. CALL FUNCTION 'BAPI_TRANSACTION_COMMIT' EXPORTING wait = abap_false. ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值