0

Although you’ll still see it in many solutions, x++ runbasebatch is the legacy pattern for background work: a single class (with dialog, pack/unpack, and run()) that you can schedule on a batch server. It’s fine for extending existing features, but new development is usually cleaner with the SysOperation pattern. Think of RunBaseBatch as the “all-in-one tool” that works, but doesn’t separate parameters from execution logic.

Practically speaking, how to create batch job in d365 x++ with RunBaseBatch means: override dialog() to add fields, use getFromDialog() to read them, persist settings with pack()/unpack(), and place your business logic in run(). You then expose the class via a menu item and let users tick “Run in the background” (or schedule it with a recurrence) so it lands in System administration > Batch jobs.

For new work, create batch job using sysoperation framework in d365 by splitting responsibilities: a [DataContractAttribute] class for parameters, a Service class with the operation method, and (optionally) a Controller to launch it. This separation makes unit testing easier, parameters self-documenting, and batch persistence automatic. You’ll mark each parm with [DataMemberAttribute], provide friendly labels, and let the runtime render a dialog that users can run once or schedule.

Even if you’ve learned x++ runbasebatch, the modern SysOperation example below shows the same warehouse scenario—relabelling ESD-sensitive storage locations for electronics—implemented with a Data Contract and Service:

// Data Contract (dialog parameters)
[DataContractAttribute]
class EsdRelabelContract
{
    WareHouseId warehouseId;
    EcoResProduct productNumber;
    boolean dryRun = true;

    [DataMemberAttribute('Warehouse')]
    public WareHouseId parmWarehouseId(WareHouseId _v = warehouseId)
    {
        warehouseId = _v; return warehouseId;
    }

    [DataMemberAttribute('ProductNumber')]
    public EcoResProduct parmProductNumber(EcoResProduct _v = productNumber)
    {
        productNumber = _v; return productNumber;
    }

    [DataMemberAttribute('DryRun')]
    public boolean parmDryRun(boolean _v = dryRun)
    {
        dryRun = _v; return dryRun;
    }
}

// Service (business logic; can run in batch)
class EsdRelabelService
{
    [SysEntryPointAttribute]
    public void run(EsdRelabelContract _c)
    {
        if (!_c.parmWarehouseId())
            throw error("Select a warehouse.");

        InventLocation loc;
        while select forupdate loc
            where loc.Warehouse == _c.parmWarehouseId()
        {
            str newLabel = strFmt("ESD-SAFE-%1", loc.LocationId);

            if (_c.parmDryRun())
            {
                info(strFmt("Would relabel %1 -> %2", loc.LocationId, newLabel));
            }
            else
            {
                ttsbegin;
                // Replace with your actual field(s) for labeling/profile
                loc.LocationProfileName = newLabel;
                loc.update();
                ttscommit;
                info(strFmt("Relabeled %1 -> %2", loc.LocationId, newLabel));
            }
        }
    }
}

Finally, when you create batch job using sysoperation framework in d365, launch the Service with a controller or menu item and encourage good habits: sensible defaults in the contract, clear labels/tooltips, and lightweight validation (e.g., “warehouse required,” “product filter optional”). For anything date-effective (prices, handling rules), pair this with validTimeStateUpdateMode(...) where appropriate, and prefer SysOperation for maintainability while reserving RunBaseBatch for legacy extensions or quick utilities.

Have a Question ?

Fill out this short form, one of our Experts will contact you soon.

Call Us Today For Your Free Consultation