Same Code different behavior Client vs Server 10.1.500.8

Well, I tried it and no, it still did not care. I solved some of my BO errors, but not the final update. instead I used UpdateExt… Then, it would allow me to delete the record. This was likely the ugliest code/logic I have ever written (there is a lot more in the rest of the requirement and not below) and it still isn’t 100%…

  this.CallService<Erp.Contracts.JobEntrySvcContract>(hJob =>{
    Erp.Tablesets.JobHeadRow row = new Erp.Tablesets.JobHeadRow(){
      Company = CompanyID,
      JobNum = oldJobNum,
      PartNum = callContextBpmData.Character03,
      Plant = callContextClient.CurrentPlant,
      JobEngineered = false,
      ChangeDescription = "Rename Job to: " + newJobNum,
    };
    dsOldJobExt.JobHead.Add(row);
    dsErrors = hJob.UpdateExt(ref dsOldJobExt, true, true, out errorsOccured);
    
   
    dsOldJob = hJob.GetByID("oldJobNum");
    dsOldJob.JobProd[0].RowMod = "D";
    hJob.Update(ref dsOldJob);
    hJob.DeleteByID(oldJobNum);
  });

I’ve been struggling with this exact same issue to try and automate the closing of maintenance jobs upon the completion of the final op. Except I couldn’t even get a direct call to JobEntry.UpdateExt to work. So I tried my go-to (read: “overly abused”) method of routing things through DynamicQuery and it worked.

The UBAQ this calls also updates via JobEntry.UpdateExt. So I remain at a loss as to how/why this works when all other, better methods failed. However, I’m also at the point were I don’t care either. At the very least, I think I take the :crown: for “ugliest solution”.

using (var svc = Ice.Assemblies.ServiceRenderer.GetService<Ice.Contracts.DynamicQuerySvcContract>(Db))
{
    var paramRow = new ExecutionParameterRow();
    paramRow.ParameterID = "JobNum";
    paramRow.ParameterValue = ttLaborDtl[0].JobNum;
    paramRow.ValueType = "nvarchar";
    qeds.Tables[1].Add(paramRow);

    baqds = svc.ExecuteByID("mnt", qeds);

    if (baqds.Tables["Results"].Rows.Count > 0)
    {
        var resultRow = baqds.Tables["Results"].Rows[0];
        resultRow["JobHead_JobClosed"] = true;
        resultRow["JobHead_ResTopicID1"] = "PASS";
        resultRow["JobHead_CommentText"] =
          "Automatically closed by " + callContextClient.CurrentUserId;
        svc.UpdateByID("mnt", baqds);
    }
}
1 Like

Add me to the list of people that received the error “Update not allowed, Engineered and Prevent Changes.” when modifying JobReleased (and JobEngineered) values.

I had what I thought was functional code performing a simple task, and it did work using WCF BO calls on JobEntry, but stopped working once I converted the code to use the service library for JobEntry (as necessary for BPMs and Functions).

I tried adding the original row into the dataset, but that didn’t work in my case. I tried about a thousand other changes, variations, etc, with no success. I even tried the changes in REST with the exact same results and error. What did work, was to remove all rows from all the tables, except the original and modified rows for JobHead. I accomplished this by creating a new Job Entry dataset (tableset) and copying the two necessary rows into the JobHead table, as shown in the abbreviated code below.

var context = Ice.Services.ContextFactory.CreateContext<ErpContext>();
using (var boJob = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.JobEntrySvcContract>(context, false))
{
	//get current dataset; 
	Erp.Tablesets.JobEntryTableset dsJeTmp = boJob.GetDatasetForTree(jobNum, 0, 0, false, "MFG,PRJ,SRV");

	//get the current datarow of interest;
	var jeRowTmp = (from fromJe in dsJeTmp.JobHead
				 select fromJe).FirstOrDefault();

	//create new dataset to pass through as parameter; 
	Erp.Tablesets.JobEntryTableset dsJe = new Erp.Tablesets.JobEntryTableset();

	//create copy of original row; 
	var origRow = dsJe.JobHead.NewRow();
	BufferCopy.Copy(jeRowTmp, origRow);
	dsJe.JobHead.Add(origRow);
	
	//create second copy of original row to become the modified row; 
	var jeRow = (Erp.Tablesets.JobHeadRow) dsJe.JobHead.NewRow();
	BufferCopy.Copy(jeRowTmp, jeRow);
	dsJe.JobHead.Add(jeRow);

	//set fields 
	jeRow.JobReleased = false;
	jeRow.RowMod = "U";

	//call methods
	boJob.ChangeJobHeadJobReleased(ref dsJe);
	boJob.Update(ref dsJe);
}

Side note - this same fix applies to the REST call as well. Remove all rows from all tables, except the original and modified rows for JobHead.

Thanks, everyone, for the help on this and the many other areas this community shares its knowledge.

1 Like

So, I looking at @Chris code, and playing around with what I had already, it seems Update() wants just the header row and gets angry if you have anything in the child tables.

(Running this in a function, for those not sure why my syntax is a bit different from the post above)

 this.CallService<Erp.Contracts.JobEntrySvcContract>(svc =>
{
        Erp.Tablesets.JobEntryTableset jets = svc.GetByID(job.JobNum);
        var emptyJets = new Erp.Tablesets.JobEntryTableset();
        //Copy the JobHead row, and only that, to the empty tableset.
        var newRow = emptyJets.JobHead.NewRow();
        BufferCopy.Copy(jets.JobHead[0], newRow);
        emptyJets.JobHead.Add(newRow);
        //modify the row
        emptyJets.JobHead[0].JobEngineered = false;
        emptyJets.JobHead[0].RowMod = "U";
        //Let this method do its thing.
        svc.ChangeJobHeadJobEngineered(ref emptyJets);
        //run the update         
        svc.Update(ref emptyJets);
});