// This is only a convenience method, because I like to keep track of the last error, with which // a transaction failed, in the status management. Makes it easier for administrators to fix the // problem and then retry that LUW. // public static void SetError(RfcUnitID tid, String errorMessage) { try { unitIDStore.SetStatus(tid.Uuid.ToString("N").ToUpper(), TidStatus.RolledBack, errorMessage); } catch (Exception) {} }
public bool CheckUnitID(RfcServerContextInfo serverContext, RfcUnitID tid) { Console.WriteLine(); Console.Write("bgRFC: Checking unit ID {0} --> ", tid.Uuid.ToString("N").ToUpper()); TidStatus status = unitIDStore.CreateEntry(tid.Uuid.ToString("N").ToUpper()); switch (status) { case TidStatus.Created: case TidStatus.RolledBack: // In these case we have to execute the bgRFC LUW. Console.WriteLine("New unit or one that had failed previously"); return(true); default: // In the remaining cases we have already executed this LUW successfully, so we // can (or rather have to) skip a second execution and send an OK code to R/3 immediately. Console.WriteLine("Already executed successfully"); return(false); } // "true" means that NCo will now execute the transaction, "false" means // that we have already executed this transaction previously, so NCo will // skip the function execution step and will immediately return an OK code to R/3. // In a real life scenario, if DB is down/unavailable, throw an exception at this point. // The .Net Connector will then abort the current bgRFC request and the R/3 backend will // try again later. // }
// React to rollback, e.g. rollback on the database public void Rollback(RfcServerContextInfo serverContext, RfcUnitID tid) { Console.WriteLine(); Console.WriteLine("bgRFC: Rollback unit ID {0}", tid.Uuid.ToString("N").ToUpper()); // Roll back all changes of the previous function modules in this LUW. // If this LUW contains only one function module, we could already do this in the processing // server function. // We assume that the error message for this UnitID has already been added to the TidStore at the // point where the error happened. // unitIDStore.SetStatus(tid.Uuid.ToString("N").ToUpper(), TidStatus.RolledBack, null); }
// React to commit, e.g. commit to the database; // Throw an exception if committing failed public void Commit(RfcServerContextInfo serverContext, RfcUnitID tid) { Console.WriteLine(); Console.WriteLine("bgRFC: Commit unit ID {0}", tid.Uuid.ToString("N").ToUpper()); // Do whatever is necessary to persist the data/changes of the function modules belonging to this LUW. // Throw an exception, if that fails. // If we know, that the LUWs that we are processing, consist of only a single function module, // the processing server function may already persist everything at the end and set the status // for that UnitID to Executed. */ // // No exception after this point */ try { unitIDStore.SetStatus(tid.Uuid.ToString("N").ToUpper(), TidStatus.Committed, null); } catch (Exception) {} }
// Clean up the resources. Backend will never send this LUW again, so no need to // protect against it any longer. public void ConfirmUnitID(RfcServerContextInfo serverContext, RfcUnitID tid) { Console.WriteLine(); Console.WriteLine("TRFC: Confirm unit ID {0}", tid.Uuid.ToString("N").ToUpper()); try { // Our implementation keeps the ones that failed, so an admin can later view error messages. String error = ""; TidStatus status = unitIDStore.GetStatus(tid.Uuid.ToString("N").ToUpper(), out error); if (status == TidStatus.RolledBack) { return; } unitIDStore.DeleteEntry(tid.Uuid.ToString("N").ToUpper()); } catch (Exception) { } }
// The backend's bgRFC runtime may at certain points ask us about the status of a bgRFC unit. public RfcUnitState GetUnitState(RfcServerContextInfo serverContext, RfcUnitID tid) { Console.WriteLine(); Console.WriteLine("bgRFC: Get unit state for unit ID {0}", tid.Uuid.ToString("N").ToUpper()); try { String error = ""; TidStatus status = unitIDStore.GetStatus(tid.Uuid.ToString("N").ToUpper(), out error); switch (status) { case TidStatus.Confirmed: return(RfcUnitState.CONFIRMED); case TidStatus.Committed: return(RfcUnitState.COMMITTED); case TidStatus.RolledBack: return(RfcUnitState.ROLLED_BACK); default: return(RfcUnitState.IN_PROCESS); } } catch (ArgumentException) { return(RfcUnitState.NOT_FOUND); } }
public void Send(RfcUnitID tId) { //if (this.con == null) //{ // throw new ERPException(Messages.NoConnectionAssigned); //} //if ((this.con.RFCHandle <= 0) && (this.con.Protocol != ClientProtocol.HttpSoap)) //{ // throw new ERPException(Messages.NoConnectionAssigned); //} //if (this._ChildSegments.Count == 0) //{ // throw new ERPException(Messages.Nosegmentsfound); //} // RFCFunction function = RFCFunctionFactory.GenerateFunctionObjectForIDOC_INBOUND_ASYNCHRONOUS(this.con.IsUnicode); IRfcFunction function = des.Repository.CreateFunction("IDOC_INBOUND_ASYNCHRONOUS"); //function.Connection = this.con; IRfcTable table = function.GetTable("IDOC_CONTROL_REC_40"); table.Append(); IRfcStructure structure = table.CurrentRow; structure["TABNAM"].SetValue(this.TABNAM); structure["MANDT"].SetValue(this.MANDT); structure["DOCNUM"].SetValue(this.DOCNUM); structure["DOCREL"].SetValue(this.DOCREL); structure["STATUS"].SetValue(this.STATUS); structure["DIRECT"].SetValue(this.DIRECT); structure["OUTMOD"].SetValue(this.OUTMOD); structure["EXPRSS"].SetValue(this.EXPRSS); structure["IDOCTYP"].SetValue(this.IDOCTYP); structure["CIMTYP"].SetValue(this.CIMTYP); structure["MESTYP"].SetValue(this.MESTYP); structure["MESCOD"].SetValue(this.MESCOD); structure["MESFCT"].SetValue(this.MESFCT); structure["STD"].SetValue(this.STD); structure["STDVRS"].SetValue(this.STDVRS); structure["STDMES"].SetValue(this.STDMES); structure["SNDPOR"].SetValue(this.SNDPOR); structure["SNDPRT"].SetValue(this.SNDPRT); structure["SNDPFC"].SetValue(this.SNDPFC); structure["SNDPRN"].SetValue(this.SNDPRN); structure["SNDSAD"].SetValue(this.SNDSAD); structure["SNDLAD"].SetValue(this.SNDLAD); structure["RCVPOR"].SetValue(this.RCVPOR); structure["RCVPRT"].SetValue(this.RCVPRT); structure["RCVPFC"].SetValue(this.RCVPFC); structure["RCVPRN"].SetValue(this.RCVPRN); structure["RCVSAD"].SetValue(this.RCVSAD); structure["RCVLAD"].SetValue(this.RCVLAD); structure["CREDAT"].SetValue(this.CREDAT); structure["CRETIM"].SetValue(this.CRETIM); structure["REFINT"].SetValue(this.REFINT); structure["REFGRP"].SetValue(this.REFGRP); structure["REFMES"].SetValue(this.REFMES); structure["ARCKEY"].SetValue(this.ARCKEY); structure["SERIAL"].SetValue(this.SERIAL); IRfcTable tData = function.GetTable("IDOC_DATA_REC_40"); for (int i = 0; i < this.Segments.Count; i++) { this.WriteSegmentToTable("0000", tData, this.Segments[i], 1); } des.ConfirmUnitID(tId); function.Invoke(des); // function.Execute(TID); // this._LastTID = Encoding.Default.GetString(TID); this._LastTID = tId.Uuid.ToString(); }
public virtual void Send() { //if (this.con == null) //{ // throw new ERPException(Messages.NoConnectionAssigned); //} //if ((this.con.RFCHandle <= 0) && (this.con.Protocol != ClientProtocol.HttpSoap)) //{ // throw new ERPException(Messages.NoConnectionAssigned); //} //if (this._ChildSegments.Count == 0) //{ // throw new ERPException(Messages.Nosegmentsfound); //} //string tID = this.con.CreateTID(); RfcUnitID tId = new RfcUnitID(RfcUnitType.TRANSACTIONAL); // String tID = con.CreateTid(); this.Send(tId); // this.con.ConfirmTID(tID); }