BPM Data Directive - Custom Code

Anyone have an idea why I am receiving the error below?

image

image

image

It’s expecting a string and you’re giving it an integer.

After looking into it, not sure why you are getting that.

Erp.BO.PO.GetByID takes an integer, and you have an integer.

Did you change that variable after creating it?

Try commenting out the code, removing the variable, and save all the way out.
Then go back and put the variable back in and uncomment the code.

Sometimes implicit casting is dumb. Try putting (int) into the expression for PONum.

Maybe use a Long and not an Int?

It was not failing on the GetByID method. It was actually failing on this line:

foreach(DataRow dRow in ds.Tables[“PODetail”].Rows)

It is not able to resolve the table name so I changed it to:

foreach(DataRow dRow in ds.Tables[1].Rows)

I’m guessing table 1 is PODetail.

1 Like

:rofl: Ahhhh!
red_herring1

I am trying to use a BPM template example to access XXX_UD fields which was posted by Brenda on several occasions. There seems to be a parenthesis missing from the template. I’ve got more errors than I can shake a stick at.

//Erp.Tables.PODetail PODetail;
//Erp.Tables.PODetail_UD PODetail_UD;

foreach(Erp.Bpm.TempTables.ReqDetailTempRow rRow in ttReqDetail)
{
  decimal Qty = Convert.ToDecimal(rRow["Number08"].ToString());
  decimal Width = Convert.ToDecimal(rRow["Number09"].ToString());
  decimal Length = Convert.ToDecimal(rRow["Number10"].ToString());
  decimal Weight = Convert.ToDecimal(rRow["Number20"].ToString());
  string QtyStr = rRow["Character01"].ToString();
  string WidStr = rRow["Character02"].ToString();
  string LenStr = rRow["Character03"].ToString();
  int ReqPONum = Convert.ToInt32(rRow["PONum"].ToString());
  int ReqPOLine = Convert.ToInt32(rRow["POLine"].ToString());
  
  using (var txscope = IceDataContext.CreateDefaultTransactionScope())
  {
    foreach (var PODetail_Recs in (from PODetail_Row in Db.PODetail
    var PODetail_Recs = (from PODetail_Row in Db.PODetail from PODetail_UD_Row in Db.PODetail_UD where PODetail_Row.Company == Session.CompanyID && PODetail_Row.SysRowID == PODetail_UD_Row.ForeignSysRowID && PODetail_Row.PONUM == ReqPONum && PODetail_Row.POLine = ReqPOLine select new { PODetail_Row, PODetail_UD_Row })).FirstOrDefault();
    {
       if (PODetail_Recs != null)
       {
         PODetail_Recs.PODetail_UD_Row.Character01 = QtyStr;
         PODetail_Recs.PODetail_UD_Row.Character02 = WidStr;
         PODetail_Recs.PODetail_UD_Row.Character03 = LenStr;
         PODetail_Recs.PODetail_UD_Row.Number08 = Qty;
         PODetail_Recs.PODetail_UD_Row.Number09 = Width;
         PODetail_Recs.PODetail_UD_Row.Number10 = Length;
         PODetail_Recs.PODetail_UD_Row.Number20 = Weight;
         Db.Validate(PODetail_Recs.PODetail_Row);
         Db.Validate(PODetail_Recs.PODetail_UD_Row);
       }
     }   /*** PODetail ***/

     txscope.Complete();
  }  
}

Here is the original template:

//Erp.Tables.XXX XXX;
//Erp.Tables.XXX_UD XXX_UD;

using (var txscope = IceDataContext.CreateDefaultTransactionScope())
{
   foreach (var XXX_Recs in (from XXX_Row in Db.XXX
   var XXX_Recs = (from XXX_Row in Db.XXX
                                 from XXX_UD_Row in Db.XXX_UD
                                 where XXX_Row.Company == Session.CompanyID
                                 && XXX_Row.SysRowID == XXX_UD_Row.ForeignSysRowID
                                 && XXX_Row.YYY == false
                                 select new { XXX_Row, XXX_UD_Row })).FirstOrDefault();
   {
      if (XXX_Recs != null)
      {
         XXX_Recs.XXX_Row.YYY = false;
         XXX_Recs.XXX_UD_Row.YYY = false;
         Db.Validate(XXX_Recs.XXX_Row);
         Db.Validate(XXX_Recs.XXX_UD_Row);
      }
   }   /*** XXX ***/
   txscope.Complete();
}

The original template looks like there are three opening parenthesis after the foreach statement and there are only two closing parenthesis. Also, it looks like it is defining XXX_Recs twice. Has anyone successfully used this template?

That template was at the beginning of ABL to C#. Things have advanced a ton since then. You don’t reference the UD, it is all handled behind the dbo view.

Something more like from this solution would be used now for writing to the Db. Or use UpdateExt for everything and you can use the objects and never write to the Db.

Thread on UpdateExt
https://www.epiusers.help/t/bpm-best-practice/92146/7

Where is the data coming from that you want to save in PODetail?

1 Like

ReqDetail.

I didn’t try to do an UpdateExt example since I am not great at them and I have no data to test with. These are all UD fields and based on what I think I saw they are the same in both files.
I have only compiled this since I don’t have any Req data.
Uncomment your fields and I think this should be close.

/* ReqDetail to PODetail */

foreach (var reqRow in ds.ReqDetail)
{


  var podList = (from podtl in Db.PODetail.With(LockHint.UpdLock) 
      where podtl.Company == reqRow.Company
      && reqRow.PONUM == podtl.PONUM
      && reqRow.ReqLine == podtl.POLine select podtl).ToList();
  
  foreach (var x in podList)
  {
    if(x!=null)
    {
    
        x.SetUDField<System.String>("LineDesc", reqRow.LineDesc);
      /*
        x.SetUDField<System.String>("Character01", reqRow.Character01);
        x.SetUDField<System.String>("Character02", reqRow.Character02);
        x.SetUDField<System.String>("Character03", reqRow.Character03);
        x.SetUDField<System.Decimal>("Number08", reqRow.Number08);
        x.SetUDField<System.Decimal>("Number09", reqRow.Number09);
        x.SetUDField<System.Decimal>("Number10", reqRow.Number10);
        x.SetUDField<System.Decimal>("Number20", reqRow.Number20);
        */
        Db.Validate();
    }
  }
}

This looks much easier to follow. I changed the first foreach statement to use ttReqDetail instead. But it must be causing an invalid cast.

foreach (var reqRow in ttReqDetail)
{
  var podList = (from podtl in Db.PODetail.With(LockHint.UpdLock) 
      where podtl.Company == reqRow.Company
      && reqRow.PONUM == podtl.PONUM
      && reqRow.ReqLine == podtl.POLine select podtl).ToList();
  
  foreach (var x in podList)
  {
    if(x != null)
    {
        x.SetUDField<System.String>("Character01", reqRow.Character01);
        x.SetUDField<System.String>("Character02", reqRow.Character02);
        x.SetUDField<System.String>("Character03", reqRow.Character03);
        x.SetUDField<System.Decimal>("Number08", reqRow.Number08);
        x.SetUDField<System.Decimal>("Number09", reqRow.Number09);
        x.SetUDField<System.Decimal>("Number10", reqRow.Number10);
        x.SetUDField<System.Decimal>("Number20", reqRow.Number20);
        Db.Validate();
    }
  }
}

I found the PODetail.Number08 was defined as an integer. The BPM works now.

2 Likes