Hey, if you know how to pass a non-serializable object or persist variables across functions without requiring me me to add each one to a Dataset Id love it hear it.
You’re smart to be wary of bypassing the BO Epicor’s data integrity relies heavily on those hidden backend triggers (like updating OrderHed summaries, setting up allocations, or flagging items for MRP). Bypassing it entirely is usually a recipe for future technical debt.
If raw REST speed over large orders is the main bottleneck, have you looked into pushing the logic into an Updatable BAQ (UBAQ) or an Epicor Function (EFx)?Instead of making heavy, repetitive standard BO calls over the API for every single line manipulation which multiplies network overhead and forces Epicor to reload tables in memory constantly you can pass a single payload to a custom Function. The Function handles the heavy lifting server-side using standard Epicor widgets or C# code.
This gives you the best of both worlds: you keep your data safe by utilizing the BO context internally, but you drastically reduce the chatty API traffic that chokes on large orders
I think we all have looked into pushing the logic server side… I feel like there are people on here stating they are doing that currently and it’s still not enough. At the end of the day, no matter where you do it, if you’re using their BOs like @GabeFranco said, you’re going to be subjected to whatever intricacies exist.
This is why I continue to state the need for a specialized focus group for the make and move (mfg/distributor) sectors to understand how we can scale with big box retailers and their growing demands to keep up. If creating your own software/apps/integrations is the only way, then I guess that’s it, but I feel that challenges like these are the exact reason we all chose an ERP system in the first place- to allow them to innovate and keep up with these changes and allow us to manufacture, move, and sell.
@utaylor I agree. ERPs were built for human interface. The next wave of Agentic commerce would fundamentally make it very difficult to operate unless ERPs evolve. Everything else is a band aid till then. Architecturally, it appears that we are going back to mainframe era Batch mode for volume, no matter how to look at it.
I think there’s room for Epicor to add new methods to the business object to support these large order/line/releases that can squeeze out performance over the standard process.
For users, reducing the number of calls on the wire, pre-validation when possible, and reducing the payload over the wire are the kind of things we can control until a better business object is available.
Me too Mark, would love to get something started with a focus group so we can discuss that instead of us all making our own apps/headless integrations to deal with the same problem.
UpdateExt is a special version of Update… Here is my simplified explanation.
Update typically takes two records… the base version (un-updated version with rowmod = “”), and the revised version (rowmod = “U”. you basically read the version before, create a copy with a U in RowMod, and then change any other values… then run the update.
UpdateExt is simplified. you only need to populate the revised values. For example, if you want to change the description on a part, all you need to do is populate the Company, the PartNum, and the Description, and then call UpdateExt. What UpdateExt does is it reads the record, populates the values needed, and calls any other validation that is needed. UpdateExt is suppost to be smart, and know all that needs to be done in addition to the regular Update.
ALSO UpdateExt can be used to ADD records as well… if it is called, and the record doesn’t exist yet, it will automatically call the Get New record routine, and populate all the defaults. Nothing special needs to be done to add vs update.
ALSO NOTE that in the Updatable Dashboards, the UpdateExt routing is what has been historically used to update and add records with Updatable Dashboards. Also with new Automation Studio, it uses the UpdateExt as well. @timshuwy
I always thought UpdateExt was the throw it over the fence and it’ll stick. One benefit it has, you can minimize the payload, I think then on the Server it does the GetByID.
UpdateExt might be used by lot of people. wonder if it’s easer to offer under specific BO to handle large volume, call it something like BO____LV and provide reference to a csv location. Focus group is the right idea. Perhaps draft a set of requirements first?
The network overhead is so small regardless of what we call I haven’t really been factoring it, it’s basically nearly the exact same timing when called from Epicors swagger.
Did another test on a fresh empty order - entered 100 sales kits in via UpdateExt - 7.8 mins. Then entered 40 of the same sales kit into that order and that took 6.1 mins.
In conclusion I think no matter what we’re running into the decaying performance problem the larger the order gets but UpdateExt does allow for bulk insert which gives big gains if you can get it all in at once!
I don’t know what the BO method is doing exactly, but it must be calling and storing the entire order dataset once and propagating that throughout the method to do its business as @GabeFranco alluded to. Probably necessary for some UpdateExt uses, but I don’t know why it would need all that data to insert new lines.
Thanks for running these test. Have you checked the datasets after each BO call? What fields were updated based on your scenarios.
I have had success to do things manually (setting the dataset the way it should be) vs calling a slow BO. You have to know what is being changed in the dataset to do this though. Maybe your processes need the extra work the BO is doing? maybe not.
Not having to call those slow BO’s will help with the MASS order loads.
I mean the UpdateExt does return the complete dataset after it does its thing, and it’s usually so large it completely breaks the swagger in these tests, but I don’t think that really helps us get around the BO methods. It just calls the method to fill the new Ds and returns it at the end of its work, who knows what else it’s doing before that.