Epicor Functions DynamicQuery Call & Put Results in BO TableSet (PartPlant)

I’ve been trying to use an Epicor Function to make a the DynamicQuery Method Call and put the results in a BO TableSet (Part.PartPlant).

I’m needing to join\compare part records from an external database to the Epicor PartPlant table and then update a few PartPlant values to match.

My Plant was to use the DynamicQuery Method Call to get the External BAQ Results into PartPlant table and then call the DynamicQuery Method again for a regular BAQ adding those results to another PartPlant table set and then run a query over both to determine the new values and then call the Part.Update to update the PartPlant records identified by the query.

But getting the results of the DynamicQuery into a DataSet or a BO Method DataTable has me going in circles.

I found a few promising posts on here but I just get errors about a Null Reference (the syntax checks out, but fails when I run it).

This post looked the cleanest and most promising but when I adjust it for the PartPlant Tableset it doesn’t work either: Epicor Functions and BAQs - Epicor ERP 10 - Epicor User Help Forum
Here is the example from the post:

foreach(DataRow BAQRow in tsBAQQueryResults.Tables[0].Rows){

Erp.Tablesets.IMWhseBinRow NewWhseBin = new Erp.Tablesets.IMWhseBinRow();

NewWhseBin.Company = BAQRow[“WhseBin_Company”].ToString();
NewWhseBin.WarehouseCode = BAQRow[“WhseBin_WarehouseCode”].ToString();
NewWhseBin.BinNum = BAQRow[“WhseBin_BinNum”].ToString();
NewWhseBin.Description = BAQRow[“WhseBin_Description”].ToString();

AcceptableBins.IMWhseBin.Insert(0,NewWhseBin);}

Here is my version for Part.PartPlant:

foreach (DataRow baqRow in dsTDM.Tables[0].Rows){

Erp.Tablesets.PartPlantRow newRow = new Erp.Tablesets.PartPlantRow();

newRow.Company    = this.callContextClient.CurrentCompany; 
newRow.Plant      = this.callContextClient.CurrentPlant; 
newRow.PartNum    = baqRow["EXT_PARTID"].ToString(); 
newRow.MinimumQty = Convert.ToDecimal(baqRow["EXT_WARNINGSTOCK"]);
newRow.MaximumQty = Convert.ToDecimal(baqRow["Calculated_Max"]); 
newRow.SafetyQty  = Convert.ToDecimal(baqRow["Calculated_Safety"]); 
newRow.RowMod     = "A";  

dsPart.PartPlant.Add(newRow);

}

Any idea what I’m missing?

Here is the error I am getting:

System.NullReferenceException: Object reference not set to an instance of an object.

I don’t know if the issue is differences in how Epicor adds rows to the tableset or what… seems like sometimes it’s .Insert(), sometimes it’s .Add() and sometimes it’s .AddRow() and I can never work out the right way to do it. I

I would expect if its a BAQ field, it’s more like Table_Field

1 Like

That is from the External BAQ… the fieldname is a bit more complex and I didn’t want to expose the real fieldname in the post….

Is this null?

Ice.Diagnostics.Log.WriteEntry($“dsPart is null = {dsPart == null} dsPart.PartPlant is null = {dsPart.PartPlant == null}”);

Probably… but I created the Variable for it and doesn’t this line initialize it?

Erp.Tablesets.PartPlantRow newRow = new Erp.Tablesets.PartPlantRow();

(Pretend I have no idea what I’m doing, I’m at that, just know enough to get into trouble)

no, you just init’d the var called newRow, not dsPart.

dsPart = new UpdExtPartTableset();

So setting up the variable on the Variables tab doesn’t initialize it?

no it just defines the holder (reference)

Updated Code, same error:

System.NullReferenceException: Object reference not set to an instance of an object.

foreach (DataRow baqRow in dsTDM.Tables[0].Rows)
{
UpdExtPartTableset dsPart = new UpdExtPartTableset();
Erp.Tablesets.PartPlantRow newRow = new Erp.Tablesets.PartPlantRow();

newRow.Company    = this.callContextClient.CurrentCompany;
newRow.Plant      = this.callContextClient.CurrentPlant;
newRow.PartNum    = baqRow\["LGM_COMPSTOCKBASE_COMPID"\].ToString();
newRow.MinimumQty = Convert.ToDecimal(baqRow\["LGM_COMPSTOCKBASE_WARNINGSTOCK"\]);
newRow.MaximumQty = Convert.ToDecimal(baqRow\["Calculated_Max"\]);
newRow.SafetyQty  = Convert.ToDecimal(baqRow\["Calculated_Safety"\]);
newRow.RowMod     = "A";

dsPart.PartPlant.Add(newRow);

}

If you feel like being a guinea pig, I am working on a spectacular LLM model.
No garantees it works in any way shape or form. I did train on an older version of Epicor so I could highly expect to see some wrong signatures, etc.

Maybe it’s helpful. Let me know!

(I just fed it your original post)

The issue is that your dsPart.PartPlant table isn’t properly initialized. Here’s the fix:

Quick Fix - Use AddRow() Method

  // First, properly initialize the dataset
  using (var partSvc = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.PartSvcContract>(Db))
  {
      var dsPart = new Erp.Tablesets.PartTableset();

      // Initialize the dataset structure - this prevents the null reference
      var tempDs = partSvc.GetNewPart(dsPart, "");
      dsPart = tempDs;
      dsPart.Part.Clear(); // Clear any temporary data

      foreach (DataRow baqRow in dsTDM.Tables[0].Rows)
      {
          // Use AddRow() instead of creating new PartPlantRow directly
          var newRow = dsPart.PartPlant.AddRow();

          newRow.Company = this.callContextClient.CurrentCompany;
          newRow.Plant = this.callContextClient.CurrentPlant;
          newRow.PartNum = baqRow["EXT_PARTID"].ToString();
          newRow.MinimumQty = Convert.ToDecimal(baqRow["EXT_WARNINGSTOCK"]);
          newRow.MaximumQty = Convert.ToDecimal(baqRow["Calculated_Max"]);
          newRow.SafetyQty = Convert.ToDecimal(baqRow["Calculated_Safety"]);
          newRow.RowMod = "A";
      }

      // Update the records
      partSvc.Update(ref dsPart);
  }

Key Changes:

  1. Proper initialization using GetNewPart() to create the dataset structure
  2. Use .AddRow() instead of new PartPlantRow()
  3. Service wrapper with proper disposal

The NullReferenceException occurs because dsPart.PartPlant is null when you create a new PartTableset(). The AddRow() method is the correct Epicor pattern for adding rows to tablesets.

1 Like