BPM Data Directive In-Transaction on JobHead requires multiple row update on JobOper

Hello,
I currently have a working BPM (data directive in-transaction) on JobHead. When a job is firmed, two user-defined note fields are successfully populated in JobHead from other tables. These work great – a one-time load that’s one-to-one with the job.

My problem is that I also need to update a user-defined note field on one or more rows (or none) in the job’s JobOper_UD table. I need to add custom code that will loop through the Job’s operations and populate the JobGenTxt_c field when a generic operation code is found. Problem is, I don’t know how to do that as my attempts create error messages that say “JobOper does not exist in the current context”.

Any suggestions on how to loop through the job’s operations and update as needed?

Thanks,
Karen

Can you please post your custom code, that will give us a starting point. Thanks,

Did you look at using a method directive instead of the data directive. Might make this a little easier.

Erp.Tables.JobHead JobHead;
Erp.Tables.JobOper JobOper;
Erp.Tables.UD02 UD02;
  
using (var txscope1 = IceDataContext.CreateDefaultTransactionScope())  /* Open the connection to the database */
{ 
	var firstJobHead = ttJobHead.FirstOrDefault(); /* Select the first ttJobHead record */ 
	if (firstJobHead != null)
	{ 
		var JJobNum = firstJobHead.JobNum; //Variable for JobNum
		
		var JobOperQuery = (from JobOperRow in Db.JobOper.With(LockHint.UpdLock) 
					where JobOper.Company == Session.CompanyID 
					&& JobOper.JobNum == JJobNum 
					&& JobOper.GenOpCode_c != null
					select JobOperRow);
		if (JobOperQuery != null)
		{
			foreach (var JobOperRow in JobOperQuery)   /* iterate through the query on the secondary table*/
			{
				var UD02Query = (from UD02Row in Db.UD02
												where UD02.Key1 == JobOperQuery.GenOpCode_c
												select UD02Row);
				JobOperRow["JobGenTxt_c"] = UD02Query.UD02_Row.GenTxt_c.ToString();
			}
		}  
	}
	Db.Validate(); /*Validate the changes */
	txscope1.Complete();  /* Commit the changes */
}
1 Like

These are the errors that I’m getting:

CS0234 The type or namespace name ‘UD02’ does not exist in the namespace ‘Erp.Tables’ (are you missing an assembly reference?)
CS1061 ‘IQueryable’ does not contain a definition for ‘GenOpCode_c’ and no extension method ‘GenOpCode_c’ accepting a first argument of type ‘IQueryable’ could be found (are you missing a using directive or an assembly reference?)
CS1061 ‘ObjectQuery’ does not contain a definition for ‘UD02_Row’ and no extension method ‘UD02_Row’ accepting a first argument of type ‘ObjectQuery’ could be found (are you missing a using directive or an assembly reference?)
CS0165 Use of unassigned local variable ‘JobOper’
CS0165 Use of unassigned local variable ‘UD02’

I believe UD tables are in the Ice schema and not Erp. So try Ice.Tables.UD02

Thank you Mark. That made a number of the errors disappear.

What is the field type of GenTxt_C? is it the same as JobGenTxt_c? If so try this. You don’t need to declare the tables, since you aren’t using them.

 var firstJobHead = ttJobHead.FirstOrDefault(); / Select the first ttJobHead record */
 
 if (firstJobHead != null)
 {
 var JJobNum = firstJobHead.JobNum; //Variable for JobNum
	var JobOperQuery = (from JobOperRow in Db.JobOper.With(LockHint.UpdLock) 
				where JobOper.Company == Session.CompanyID 
				&& JobOper.JobNum == JJobNum 
				&& JobOper.GenOpCode_c != null
				select JobOperRow);
	if (JobOperQuery != null)
	{
		using (var txscope1 = IceDataContext.CreateDefaultTransactionScope()) /* Open the connection to the database /
		{
			foreach (var JobOperRow in JobOperQuery)   /* iterate through the query on the secondary table*/
			{
				var UD02Query = (from UD02Row in Db.UD02
							      where UD02.Key1 == JobOperQuery.GenOpCode_c
                                                          select UD02Row).FirstOrDefault();
				JobOperRow.JobGenTxt_c = UD02Query.GenTxt_c;
			}
		Db.Validate(); /*Validate the changes */
		txscope1.Complete();  /* Commit the changes */

		}  
	}

}

Thank you for your code. I copied it and received the following errors:

CS0120 An object reference is required for the non-static field, method, or property ‘JobOper.Company’
CS0120 An object reference is required for the non-static field, method, or property ‘JobOper.JobNum’
CS0120 An object reference is required for the non-static field, method, or property ‘JobOper.GenOpCode_c’
CS1579 foreach statement cannot operate on variables of type ‘?’ because ‘?’ does not contain a public definition for ‘GetEnumerator’
CS0120 An object reference is required for the non-static field, method, or property ‘UD02.Key1’

you need to add foreach loop to your second block, then select the results into List for this block and the next one inside it-if needed-
image

image

Just looking at the code… there are several improvements that can be made… but this section is probably your issue…

OLD CODE:

if (JobOperQuery != null) {
    foreach (var JobOperRow in JobOperQuery) /* iterate through the query on the secondary table*/ {
        var UD02Query = (from UD02Row in Db.UD02 where UD02.Key1 == JobOperQuery.GenOpCode_c select UD02Row);
        JobOperRow["JobGenTxt_c"] = UD02Query.UD02_Row.GenTxt_c.ToString();
    }
}

New CODE…

  1. uses a Lambda expression
  2. for efficiency, we only select the ONE FIELD we need (instead of the entire record).
  3. also checked for null value on UD02Record
if (JobOperQuery != null) {
    foreach (var JobOperRow in JobOperQuery) /* iterate through the query on the secondary table*/ {
        var UD02Record = Db.UD02.Where(x => x.Company == firstJobHead.Company && x.Key1 == JobOperQuery.GenOpCode_c).Select(x => new { x.GenTxt_c }).FirstOrDefault();
        if (UD02Record != null) {
            JobOperRow["JobGenTxt_c"] = UD02Query.GenTxt_c.ToString();
        }
    }
}

Here’s the latest code updates and syntax errors:

Erp.Tables.JobHead JobHead;
Erp.Tables.JobOper JobOper;
Ice.Tables.UD02 UD02;

using (var txscope1 = IceDataContext.CreateDefaultTransactionScope())
{
var firstJobHead = ttJobHead.FirstOrDefault();
string[] SaveGenText = new String[5000];

if (firstJobHead != null)
{ 
	var JJobNum = firstJobHead.JobNum;
	var JGenOpCode = (String)null; 
	
	var JobOperQuery = (from JobOperRow in Db.JobOper.With(LockHint.UpdLock) 
				where JobOper.Company == Session.CompanyID 
				&& JobOper.JobNum == JJobNum 
				&& JobOper.GenOpCode_c != null
				select JobOperRow);

	if (JobOperQuery != null) {
	foreach (var JobOperRow in JobOperQuery) {
	        var UD02Record = Db.UD02.Where(x => x.Company == firstJobHead.Company && x.Key1 == JobOperQuery.GenOpCode_c).Select(x => new { x.GenTxt_c }).FirstOrDefault();
	        if (UD02Record != null) {
	            JobOperRow["JobGenTxt_c"] = UD02Record.GenTxt_c.ToString();
	        }
	    }
	}

}
Db.Validate(); 
txscope1.Complete();

}

Syntax Errors:

CS1061 ‘IQueryable’ does not contain a definition for ‘GenOpCode_c’ and no extension method ‘GenOpCode_c’ accepting a first argument of type ‘IQueryable’ could be found (are you missing a using directive or an assembly reference?)
CS0165 Use of unassigned local variable ‘JobOper’

Try this

Erp.Tables.JobHead JobHead;
Erp.Tables.JobOper JobOper;
Ice.Tables.UD02 UD02;

using (var txscope1 = IceDataContext.CreateDefaultTransactionScope())
{
var firstJobHead = ttJobHead.FirstOrDefault();
string[] SaveGenText = new String[5000];

if (firstJobHead != null)
{ 
	var JJobNum = firstJobHead.JobNum;
	var JGenOpCode = (String)null; 
	
	var JobOperQuery = (from JobOperRow in Db.JobOper.With(LockHint.UpdLock) 
				where JobOperRow.Company == Session.CompanyID 
				&& JobOperRow.JobNum == JJobNum 
				&& JobOperRow.GenOpCode_c != null
				select JobOperRow);

	if (JobOperQuery != null) {
	foreach (var JobOperRow in JobOperQuery) {
	        var UD02Record = Db.UD02.Where(x => x.Company == firstJobHead.Company && x.Key1 == JobOperRow.GenOpCode_c).Select(x => new { x.GenTxt_c }).FirstOrDefault();
	        if (UD02Record != null) {
	            JobOperRow["JobGenTxt_c"] = UD02Record.GenTxt_c.ToString();
	        }
	    }
	}

}
Db.Validate(); 
txscope1.Complete();
}

Tim there is a need to loop through JobOper records to check all operations linked to ttJobHead,

@danbedwards
it is better to put txscope line after the IF condition, so it won’t cause an error when there is no ttRecord

1 Like

I honestly never looked at the code, just fixed the mistakes. :slight_smile: I would do a few things different.

2 Likes

Mr Edwards – you nailed it!
Thank you very much for fixing the syntax.
It works like a charm!
Thanks again,
Karen

1 Like