BAQ BPM Processing with Db Commit

Hi All,

I’m working on a workbench where the user can select a number of PCIDs and then, with a click of a button, remove the stock from PCID and then place the stock on NonConformance.
Both parts of this will work independently (remove the stock from the PCID with one update and place the stock on NonConformance in another), but when doing one after another in code, the nonconformance doesn’t see the stock in the bin… it’s not committed.
I’ve tried using Db.Validate(), but this makes no change.
Trying to use using(var txscope = IceDataContext.CreateDefaultTransactionScope()) along with txScope.Complete(), but this prevents either update from making changes at all even using Db.Validate AND TransactionScope

The services that I am using for the changes are:
var NonConfBO = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.NonConfSvcContract>(this.Db,true);
var PkgControlIDBuildSplitMergeBO = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.PkgControlIDBuildSplitMergeSvcContract>(this.Db,true);

Anyone have any ideas:

  • Why using the TransactionScope causes the service updates to not be committed to the database after BAQ BPM is finished without error?
  • How to commit the transaction mid-BPM when using services?

For people keen to pull apart my crappy coding:
/Remove From PCIDs/

var NonConfBO = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.NonConfSvcContract>(this.Db,true);
using (NonConfBO)
{
//Comment out the transaction scope as it prevents updates
//using(var txscope = IceDataContext.CreateDefaultTransactionScope()) 
//{

  foreach (var ttResults_Row in (
    from row in ttResults 
    where /*row.RowMod == "U"  
    && */row.Calculated_Selected == true
    select row))
  {
    var PCID = ttResults_Row["PkgControlHeader_PCID"].ToString();
    
    this.PublishInfoMessage("Removing PCID: "+PCID, Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual, "", "");
    
    var PkgControlIDBuildSplitMergeBO = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.PkgControlIDBuildSplitMergeSvcContract>(this.Db,true);
    
    using (PkgControlIDBuildSplitMergeBO) 
    {
      // SOURCE DATASET
      // Get the Source dataset.  Easy way to create a row.  We will null ou the PCID so that source is inventory
      PkgControlIDBuildSplitMergeBO.GetSourcePCID(PCID, false, ref this.dsSourcePCID);
      
      // Null out the PCID  we are moving from Dest to source so the source is just inventory
      foreach (var SourceRow in dsSourcePCID.PCIDBuildSplitMergeSource)
      {
        SourceRow.PCID = "";
      }
  
      // DEST DATASET
      // Get the Dest Dataset
      PkgControlIDBuildSplitMergeBO.GetDestPCID(PCID, true, ref this.dsDestPCID);
      
      // Process the PCID Items, including creating the NonConformance Record
      foreach (var DestItemRow in dsDestPCID.PCIDBuildSplitMergeDestItem)
      {
        // Set the Item in the PCID for processing (removal)
        DestItemRow.SelectedForAction = true;
        DestItemRow.RowMod = "U";
        
        //NONCONFORMANCE
        // Add NonConformance Record
        this.dsNonConformance = NonConfBO.AddNonConf("Inventory");
        var NonConfRecord = dsNonConformance.NonConf.FirstOrDefault();
        
        System.String PartRevisionNum;
        System.String UOM;
        System.String WarehouseCode;
        System.Boolean LotTracked;
        System.Boolean DimTracked;
        System.String WareHseCodeDesc;
        System.String BinNum;
        NonConfBO.GetPartInfo(
                      DestItemRow.ItemPartNum,
                      out PartRevisionNum,
                      out UOM,
                      out WarehouseCode,
                      out LotTracked,
                      out DimTracked,
                      out WareHseCodeDesc,
                      out BinNum);
                      
        // Update with the Item details we are removing from the PCID
        NonConfRecord["PartNum"] = DestItemRow.ItemPartNum;
        NonConfRecord["EmpID"] = "AMA";   // I don't think this is required
        NonConfRecord["ScrapUM"] = UOM;
        NonConfRecord["WarehouseCode"] = ttResults_Row.PkgControlHeader_WarehouseCode;
        NonConfRecord["BinNum"] = ttResults_Row.PkgControlHeader_BinNum;
        NonConfRecord["TranUOM"] = UOM;
        NonConfRecord["EmpIDName"] = "Andrew May";   // I don't think this is required
        NonConfRecord["PartNumPartDescription"] = "AM PCID Part"; //Need to find where to pull this from 
        NonConfRecord["WarehouseCodeDescription"] = "Main Warehouse";
        
        
        NonConfBO.GetAvailableQty(ref this.dsNonConformance); // Should move this to just before doing the Process, after removing from PCID
        NonConfBO.OnChangeTranQty(DestItemRow.ItemQuantity, ref this.dsNonConformance);

        // !!! Here should go the code to get the reson code. Could be a pop up asking user what reason.
        NonConfRecord["ReasonCode"] = "Faulty";
        NonConfRecord["ReasonDescription"] = "Faulty";
        NonConfRecord["RequestMove"] = false;
        // ^^^

        NonConfBO.OnChangeBinNum(ttResults_Row.PkgControlHeader_BinNum, false, ref this.dsNonConformance);

        NonConfRecord["ToBinNum"] = ttResults_Row.PkgControlHeader_BinNum;  //We're not requesting move so the To Bin should be the same as BinNum
        NonConfRecord["PCID"] = PCID; // This is not currently supported by epicor, so updating manually

        //dsNonConformances.NonConf.Add(dsNonConformance.NonConf.FirstOrDefault()); //This doesn't work.  It would be nice to just copy the record into the table. I think Clone is what's required, but needs to be worked out.
        
        // Copy the NonConformance record into the dsNonConformances list to be processed later
        var NewNonConfRow = dsNonConformances.NonConf.NewRow();
          NewNonConfRow["Company"] = NonConfRecord["Company"];
          NewNonConfRow["Quantity"] = NonConfRecord["Quantity"];
          NewNonConfRow["ReasonCode"] = NonConfRecord["ReasonCode"];
          NewNonConfRow["JobNum"] = NonConfRecord["JobNum"];
          NewNonConfRow["AssemblySeq"] = NonConfRecord["AssemblySeq"];
          NewNonConfRow["MtlSeq"] = NonConfRecord["MtlSeq"];
          NewNonConfRow["PartNum"] = NonConfRecord["PartNum"];
          NewNonConfRow["RevisionNum"] = NonConfRecord["RevisionNum"];
          NewNonConfRow["ScrapLaborCost"] = NonConfRecord["ScrapLaborCost"];
          NewNonConfRow["ScrapBurdenCost"] = NonConfRecord["ScrapBurdenCost"];
          NewNonConfRow["ScrapMaterialCost"] = NonConfRecord["ScrapMaterialCost"];
          NewNonConfRow["ScrapMaterialBurCost"] = NonConfRecord["ScrapMaterialBurCost"];
          NewNonConfRow["TrnTyp"] = NonConfRecord["TrnTyp"];
          NewNonConfRow["DimCode"] = NonConfRecord["DimCode"];
          NewNonConfRow["OprSeq"] = NonConfRecord["OprSeq"];
          NewNonConfRow["ResourceID"] = NonConfRecord["ResourceID"];
          NewNonConfRow["Description"] = NonConfRecord["Description"];
          NewNonConfRow["EntryPerson"] = NonConfRecord["EntryPerson"];
          NewNonConfRow["EmpID"] = NonConfRecord["EmpID"];
          NewNonConfRow["InspectionPending"] = NonConfRecord["InspectionPending"];
          NewNonConfRow["ScrapUM"] = NonConfRecord["ScrapUM"];
          NewNonConfRow["InspectedBy"] = NonConfRecord["InspectedBy"];
          NewNonConfRow["InspectorID"] = NonConfRecord["InspectorID"];
          NewNonConfRow["DimConvFactor"] = NonConfRecord["DimConvFactor"];
          NewNonConfRow["LaborHedSeq"] = NonConfRecord["LaborHedSeq"];
          NewNonConfRow["LaborDtlSeq"] = NonConfRecord["LaborDtlSeq"];
          NewNonConfRow["PassedQty"] = NonConfRecord["PassedQty"];
          NewNonConfRow["FailedQty"] = NonConfRecord["FailedQty"];
          NewNonConfRow["SysDate"] = NonConfRecord["SysDate"];
          NewNonConfRow["SysTime"] = NonConfRecord["SysTime"];
          NewNonConfRow["PsdCommentText"] = NonConfRecord["PsdCommentText"];
          NewNonConfRow["FldCommentText"] = NonConfRecord["FldCommentText"];
          NewNonConfRow["PurPoint"] = NonConfRecord["PurPoint"];
          NewNonConfRow["VendorNum"] = NonConfRecord["VendorNum"];
          NewNonConfRow["LotNum"] = NonConfRecord["LotNum"];
          NewNonConfRow["WarehouseCode"] = NonConfRecord["WarehouseCode"];
          NewNonConfRow["BinNum"] = NonConfRecord["BinNum"];
          NewNonConfRow["ScrapSubCost"] = NonConfRecord["ScrapSubCost"];
          NewNonConfRow["QtyFrm"] = NonConfRecord["QtyFrm"];
          NewNonConfRow["TranID"] = NonConfRecord["TranID"];
          NewNonConfRow["DMRNum"] = NonConfRecord["DMRNum"];
          NewNonConfRow["PONum"] = NonConfRecord["PONum"];
          NewNonConfRow["POLine"] = NonConfRecord["POLine"];
          NewNonConfRow["PORelNum"] = NonConfRecord["PORelNum"];
          NewNonConfRow["Plant"] = NonConfRecord["Plant"];
          NewNonConfRow["RMANum"] = NonConfRecord["RMANum"];
          NewNonConfRow["RMALine"] = NonConfRecord["RMALine"];
          NewNonConfRow["RMAReceipt"] = NonConfRecord["RMAReceipt"];
          NewNonConfRow["RMADisp"] = NonConfRecord["RMADisp"];
          NewNonConfRow["CommentText"] = NonConfRecord["CommentText"];
          NewNonConfRow["MaterialMtlCost"] = NonConfRecord["MaterialMtlCost"];
          NewNonConfRow["MaterialLabCost"] = NonConfRecord["MaterialLabCost"];
          NewNonConfRow["MaterialSubCost"] = NonConfRecord["MaterialSubCost"];
          NewNonConfRow["MaterialBurCost"] = NonConfRecord["MaterialBurCost"];
          NewNonConfRow["OpCode"] = NonConfRecord["OpCode"];
          NewNonConfRow["ToWarehouseCode"] = NonConfRecord["ToWarehouseCode"];
          NewNonConfRow["ToBinNum"] = NonConfRecord["ToBinNum"];
          NewNonConfRow["AQMNCMNum"] = NonConfRecord["AQMNCMNum"];
          NewNonConfRow["RequestMove"] = NonConfRecord["RequestMove"];
          NewNonConfRow["MoveCostsToDMR"] = NonConfRecord["MoveCostsToDMR"];
          NewNonConfRow["TranDocTypeID"] = NonConfRecord["TranDocTypeID"];
          NewNonConfRow["SysRowID"] = NonConfRecord["SysRowID"];
          NewNonConfRow["PCID"] = NonConfRecord["PCID"];
          NewNonConfRow["AttributeSetID"] = NonConfRecord["AttributeSetID"];
          NewNonConfRow["AvailableQty"] = NonConfRecord["AvailableQty"];
          NewNonConfRow["Closed"] = NonConfRecord["Closed"];
          NewNonConfRow["EnableSN"] = NonConfRecord["EnableSN"];
          NewNonConfRow["FromOpCode"] = NonConfRecord["FromOpCode"];
          NewNonConfRow["FromOprSeq"] = NonConfRecord["FromOprSeq"];
          NewNonConfRow["LegalNumber"] = NonConfRecord["LegalNumber"];
          NewNonConfRow["LegalNumberMessage"] = NonConfRecord["LegalNumberMessage"];
          NewNonConfRow["MtlSourceTrnType"] = NonConfRecord["MtlSourceTrnType"];
          NewNonConfRow["ProcessID"] = NonConfRecord["ProcessID"];
          NewNonConfRow["ReasonDescription"] = NonConfRecord["ReasonDescription"];
          NewNonConfRow["ResourceGrpID"] = NonConfRecord["ResourceGrpID"];
          NewNonConfRow["SerialControlPlant"] = NonConfRecord["SerialControlPlant"];
          NewNonConfRow["SerialControlPlant2"] = NonConfRecord["SerialControlPlant2"];
          NewNonConfRow["SerialControlPlantIsFromPlt"] = NonConfRecord["SerialControlPlantIsFromPlt"];
          NewNonConfRow["TranQty"] = NonConfRecord["TranQty"];
          NewNonConfRow["TranUOM"] = NonConfRecord["TranUOM"];
          NewNonConfRow["TrnTypDescription"] = NonConfRecord["TrnTypDescription"];
          NewNonConfRow["WrkCntrDesc"] = NonConfRecord["WrkCntrDesc"];
          NewNonConfRow["AllowNegQty"] = NonConfRecord["AllowNegQty"];
          NewNonConfRow["BitFlag"] = NonConfRecord["BitFlag"];
          NewNonConfRow["AssemblySeqDescription"] = NonConfRecord["AssemblySeqDescription"];
          NewNonConfRow["BinNumDescription"] = NonConfRecord["BinNumDescription"];
          NewNonConfRow["DimCodeDimCodeDescription"] = NonConfRecord["DimCodeDimCodeDescription"];
          NewNonConfRow["DMRNumPartDescription"] = NonConfRecord["DMRNumPartDescription"];
          NewNonConfRow["EmpIDName"] = NonConfRecord["EmpIDName"];
          NewNonConfRow["FromOpCodeOpDesc"] = NonConfRecord["FromOpCodeOpDesc"];
          NewNonConfRow["InspectorIDName"] = NonConfRecord["InspectorIDName"];
          NewNonConfRow["JobNumPartDescription"] = NonConfRecord["JobNumPartDescription"];
          NewNonConfRow["OpCodeOpDesc"] = NonConfRecord["OpCodeOpDesc"];
          NewNonConfRow["PartNumSellingFactor"] = NonConfRecord["PartNumSellingFactor"];
          NewNonConfRow["PartNumTrackDimension"] = NonConfRecord["PartNumTrackDimension"];
          NewNonConfRow["PartNumIUM"] = NonConfRecord["PartNumIUM"];
          NewNonConfRow["PartNumPricePerCode"] = NonConfRecord["PartNumPricePerCode"];
          NewNonConfRow["PartNumSalesUM"] = NonConfRecord["PartNumSalesUM"];
          NewNonConfRow["PartNumTrackSerialNum"] = NonConfRecord["PartNumTrackSerialNum"];
          NewNonConfRow["PartNumTrackLots"] = NonConfRecord["PartNumTrackLots"];
          NewNonConfRow["PartNumPartDescription"] = NonConfRecord["PartNumPartDescription"];
          NewNonConfRow["PlantName"] = NonConfRecord["PlantName"];
          NewNonConfRow["POLinePartNum"] = NonConfRecord["POLinePartNum"];
          NewNonConfRow["POLineLineDesc"] = NonConfRecord["POLineLineDesc"];
          NewNonConfRow["POLineVenPartNum"] = NonConfRecord["POLineVenPartNum"];
          NewNonConfRow["ResourceIDDescription"] = NonConfRecord["ResourceIDDescription"];
          NewNonConfRow["RMALineLineDesc"] = NonConfRecord["RMALineLineDesc"];
          NewNonConfRow["ToBinNumDescription"] = NonConfRecord["ToBinNumDescription"];
          NewNonConfRow["ToWareHouseCodeDescDescription"] = NonConfRecord["ToWareHouseCodeDescDescription"];
          NewNonConfRow["VendorNumAddress2"] = NonConfRecord["VendorNumAddress2"];
          NewNonConfRow["VendorNumName"] = NonConfRecord["VendorNumName"];
          NewNonConfRow["VendorNumTermsCode"] = NonConfRecord["VendorNumTermsCode"];
          NewNonConfRow["VendorNumDefaultFOB"] = NonConfRecord["VendorNumDefaultFOB"];
          NewNonConfRow["VendorNumState"] = NonConfRecord["VendorNumState"];
          NewNonConfRow["VendorNumVendorID"] = NonConfRecord["VendorNumVendorID"];
          NewNonConfRow["VendorNumCurrencyCode"] = NonConfRecord["VendorNumCurrencyCode"];
          NewNonConfRow["VendorNumCity"] = NonConfRecord["VendorNumCity"];
          NewNonConfRow["VendorNumCountry"] = NonConfRecord["VendorNumCountry"];
          NewNonConfRow["VendorNumAddress3"] = NonConfRecord["VendorNumAddress3"];
          NewNonConfRow["VendorNumAddress1"] = NonConfRecord["VendorNumAddress1"];
          NewNonConfRow["VendorNumZIP"] = NonConfRecord["VendorNumZIP"];
          NewNonConfRow["WarehouseCodeDescription"] = NonConfRecord["WarehouseCodeDescription"];
          NewNonConfRow["RowMod"] = NonConfRecord["RowMod"];


        // Add the new row into dsNonConformances dataset for processing
        dsNonConformances.NonConf.Add(NewNonConfRow);
        this.PublishInfoMessage("Updating DestItemRow: "+DestItemRow.ItemPartNum+", Qty: " + NewNonConfRow["Quantity"].ToString(), Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual, "", "");

      }
  
      PkgControlIDBuildSplitMergeBO.RemoveFromDestPCID(ref this.dsDestPCID, ref this.dsSourcePCID);
    }
    
    ttResults_Row["Calculated_Selected"] = false;
    
  }

 Db.Validate();
//Comment out the transaction scope as it prevents updates
// txscope.Complete();
//}
  //NonConfBO.GetAvailableQty(ref this.dsNonConformances); // TEST!!!! Seeing if this will correctly update the AvailableQty for all the rows
  
  System.Boolean UserInputRequired;
  System.String ErrorMessage;
  NonConfBO.PreUpdate(ref dsNonConformances, out UserInputRequired, out ErrorMessage);
  if (UserInputRequired) this.PublishInfoMessage("Error In NonConformance Update: "+ErrorMessage, Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual, "", "");
  else NonConfBO.Update(ref dsNonConformances);
}

On further analysis, this appears to just be an issue with the PkgControlIDBuildSplitMergeSvcContract. The following will complete without error, however, it will not commit to the database unless I remove the txscope:

using(var txscope = Erp.ErpContext.CreateDefaultTransactionScope()) //IceContext and IceDataContext rather than Erp.ErpContext also tested here
{

  foreach (var ttResults_Row in (
    from row in ttResults 
    where /*row.RowMod == "U"  
    && */row.Calculated_Selected == true
    select row))
  {
    var PCID = ttResults_Row["PkgControlHeader_PCID"].ToString();
    
    this.PublishInfoMessage("Removing PCID: "+PCID, Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual, "", "");
    
    using (var PkgControlIDBuildSplitMergeBO = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.PkgControlIDBuildSplitMergeSvcContract>(this.Db,true)) 
    {
      // SOURCE DATASET
      // Get the Source dataset.  Easy way to create a row.  We will null ou the PCID so that source is inventory
      PkgControlIDBuildSplitMergeBO.GetSourcePCID(PCID, false, ref this.dsSourcePCID);
      
      // Null out the PCID  we are moving from Dest to source so the source is just inventory
      foreach (var SourceRow in dsSourcePCID.PCIDBuildSplitMergeSource)
      {
        SourceRow.PCID = "";
      }
  
      // DEST DATASET
      // Get the Dest Dataset
      PkgControlIDBuildSplitMergeBO.GetDestPCID(PCID, true, ref this.dsDestPCID);
      
      // Process the PCID Items, including creating the NonConformance Record
      foreach (var DestItemRow in dsDestPCID.PCIDBuildSplitMergeDestItem)
      {
        // Set the Item in the PCID for processing (removal)
        DestItemRow.SelectedForAction = true;
        DestItemRow.RowMod = "U";

        this.PublishInfoMessage("Updating DestItemRow: "+DestItemRow.ItemPartNum+", Qty: ", Ice.Common.BusinessObjectMessageType.Information, Ice.Bpm.InfoMessageDisplayMode.Individual, "", "");
      }
      PkgControlIDBuildSplitMergeBO.RemoveFromDestPCID(ref this.dsDestPCID, ref this.dsSourcePCID);
    }
    
    ttResults_Row["Calculated_Selected"] = false;
    
  } //foreach (var ttResults_Row

  Db.Validate(); 
  // Comment out the transaction scope as it prevents updates
  txscope.Complete();
} //End Transaction Scope

Any ideas as to how I can get this to work or what I’m doing wrong would be appreciated.