Invalid cast error on several BPMs are UD field update

,

This is on Epicor 10.2.400.14 .

We are in the implementation phase from 9.05.702 to 10.2.400.14 for our upgrade.

I have used Solution Manager to copy our Customizations, BPMs, and such from our Test database to Pilot. Then, we used DMT to update our UD fields to match what we have the in the Test database. However, after this process in our new Pilot database we get an error every time we are comparing or checking a UD field in our BPMs. The error we are getting from multiple BPMs is below. It is an invalid cast issue.

I did a regenerate of the data model (By turning off Task agent, App Servers, Regen, turning all back on) following our DMT updates and the tables and data model now show in sync. I have checked and the BPMs match what we have in our Test database (that work properly without an error). I am also comparing the ZField table in the database (UD fields) from the two databases and they match, except the UDPredictiveSearchID where it sometimes says NULL and sometimes None). I cannot find any other differences between UD fields or BPMs on the two databases.

Is there an issue with putting in UD fields using the DMT tool? Is this a known issue after exporting and importing BPMs into a different database with Solutions Workbench? Is there anywhere else I can check to locate a difference between the two databases? Is there a Company setting that would control explicit casting of UD fields?

BPM runtime caught an unexpected exception of ‘InvalidCastException’ type.

See more info in the Inner Exception section of Exception Details.

Server Side Exception

BPM runtime caught an unexpected exception of ‘InvalidCastException’ type.

See more info in the Inner Exception section of Exception Details.

Exception caught in: Epicor.ServiceModel

Error Detail

============

Description: BPM runtime caught an unexpected exception of ‘InvalidCastException’ type.

See more info in the Inner Exception section of Exception Details.

Program: Customer.OnChangeofCustomerAddr.dll

Method: A001_CustomCodeAction

Original Exception Type: InvalidCastException

Client Stack Trace

==================

at Epicor.ServiceModel.Channels.ImplBase`1.ShouldRethrowNonRetryableException(Exception ex, DataSet[] dataSets)

at Erp.Proxy.BO.CustomerImpl.OnChangeofCustomerAddr(CustomerDataSet ds, Int32 CustNum, String ProposedVal, String AddrField)

at Erp.Adapters.CustomerAdapter.OnChangeofCustomerAddr(Int32 custNum, String proposedVal, String addrField)

Inner Exception

===============

Specified cast is not valid.

What’s the code look like in your custom action

So, the same code was working in our Test database, then not in our Pilot database (they have the same database version and everything else I can find). Here is an example of the code that was causing the error in Pilot:

int wkInt = (int)ttCustomerRow["Number01"]

We have been able to get the follow code to work in the new database:

int wkDays = System.Convert.ToInt32(ttShipToRow ["Number02"]);

Does this sound like a correct workaround? I’m concerned we are going to be getting more issues with the UD fields in other areas of our testing if the issue lies with the UD fields.

both of those are valid. Try regenerating Pilot again, recycling your app server, and clear your client cache.

Agreed. They both seem correct and work in our TEST database, but in Pilot we get the error.

I reran the regenerate Data Model process I saw here from Rich Reilly:

– Stop the Task Agent(s) (if a task agent is running it can keep the AppServer alive)
– Stop the AppServer(s) (this is done by clicking 'Stop Application Pool,' correct?)
– Regenerate the DataModel
– Start the AppServer(s)
– Start the Task Agent(s)

I just swapped them out and got the exact same result; works with the Convert.ToInt32, but error on the (int) line.

Here is the entire BPM, it checks the Country Code to set Number01 to a predetermined value:

foreach (var ttCustomer_iterator in (from ttCustomer_Row in ttCustomer 
             where string.Equals(ttCustomer_Row.RowMod, IceRow.ROWSTATE_UPDATED, StringComparison.OrdinalIgnoreCase) 
                || string.Equals(ttCustomer_Row.RowMod, IceRow.ROWSTATE_ADDED, StringComparison.OrdinalIgnoreCase) 

    select ttCustomer_Row))
{  
    var ttCustomerRow = ttCustomer_iterator;
      int wkInt = (int)ttCustomerRow["Number01"];
//    int wkInt = System.Convert.ToInt32(ttCustomerRow["Number01"]);
    if ( ( ProposedVal == "1" ) && ( wkInt == 5 ) )        ttCustomerRow["Number01"] = 2;
    else if ( ( ProposedVal != "1" )  && ( wkInt == 2 ) )  ttCustomerRow["Number01"] = 5;
}

Sometimes repeating the steps of regen, recycle, and clear client cache can fix these issues. I don’t think it’s code related, I think its a cache of the data model related.

Thanks for the help, Aaron. I went ahead and did the whole process for regen again, but unfortunately the same situation is happening. It is working with the Convert.ToInt32 code, but not the other.

The only thing I question in doing the steps I listed above on Regen Data model is if I’m possibly not stopping the AppServer by clicking ‘Stop Application Pool.’ Is there another, better method? I haven’t had any issues in adding UD fields in our Test system before this DMT update to Pilot, but possibly I have just gotten lucky before. Otherwise, I agree, this makes little sense.

when I add fields I just do it via regen data model + recycle app server. I also do this off hours, not sure if that makes a difference. I know killing the task agent and turning off/on the app server is definitely the proper way to do it, but this way is sufficient.

So just so I understand, you have a test environment with new UD fields and it works great with your BPMs. You wished to move those new UD fields to Pilot, so you packed them up in a solution, imported it into pilot, regen + recycle, and now there is an issue when running DMT for records against tables with those UD fields (and BPMs involved) in pilot?

@josecgomez pointed out in a post that System.Convert was also checking for nulls. Is there a value in Number01?

1 Like

I use the form
ttOrderHedRow.UDField<System.String>("MyNewColumn")
When referencing UD fields in custom code.

You could try
ttCustomerRow.UDField<System.Int32>("Number01")

From the 'C# Programming Guide(onversion from ABL)

Thats a decimal

1 Like

So he should use

int wkInt = Decimal.ToInt32(ttCustomerRow["Number01"]);

Yeah he need to access it as a decimal. From there, he can convert many different ways to his desired type.