MB-500 study materials
MB-500 study resources

Adding a freight terms field without breaking a 24-million-row table

MB-500 · Put your knowledge to work in context.

All case studies

Adding a freight terms field without breaking a 24-million-row table

Contoso must add a 'Freight terms' value to sales orders. It should default from the customer, remain editable on the sales order header only while the order is open, be validated against a fixed list of six terms plus 'Not applicable', be exposed to a mobile app through OData, and appear on the Microsoft-owned Sales invoice SSRS report. SalesTable holds 24 million rows and participates in the hottest set-based queries. A developer proposes adding the column as a non-nullable field with a default value, enforcing editability by clearing the AllowEdit property in the standard form's designer, and copying the Microsoft report so its design can be changed. The go-live patch window is 30 minutes.

1. Evaluate the proposed field design and specify the AOT elements to create.

Read the worked answer

The non-nullable-with-default proposal is the risk. Adding a column through a table extension is metadata-driven, and a nullable column with no default is added without rewriting the table; a NOT NULL column with a default forces SQL Server to populate 24 million rows, which will blow the 30-minute window and hold locks on the hottest table in the system.

Build:

  • Base enum ConFreightTerms with the six values plus None, marked extensible so values can be added later via enum extension.
  • EDT based on that enum (for example ConFreightTermsId) rather than putting the enum type directly on the field - this gives one place to change the type and keeps labels consistent.
  • Table extension on SalesTable adding the field, nullable, no default, with a proper label and help text.
  • Table extension on CustTable only if the default must be stored on the customer, plus an extension method defaultFreightTerms() on CustTable.
  • A relation from the field to the enum/table if reporting needs to display terms independently, and an index only if queries truly filter on it - a low-cardinality column rarely earns one.

2. How should the default, the editability rule and the validation be implemented so they cannot be bypassed?

Read the worked answer

Three separate enforcement points, because each protects a different entry path:

  1. Default - put it in the table, not the form: extend SalesTable.initValue() or the initFromSalesTable/customer defaulting path with a CoC class so orders created by data entities, services and batch also get the value. A form-level default only covers manual entry.
  2. Editability - a UI rule belongs in the UI layer: extend the form data source's active() (CoC on FormDataSource) to set the field's allowEdit from a table extension method such as isFreightTermsEditable(), which inspects the sales status/document status. Never edit the standard form's design properties - a copy of the form becomes unmaintainable and will not receive Microsoft fixes.
  3. Validation - UI state is advisory. Enforce in validateWrite() (table extension) so OData, imports and ISV code are covered: the value must be non-empty when the order is open and must be unchanged after confirmation. Return checkFailed() with a label, not an exception.

Also guard the data entity path explicitly, because entity imports bypass form logic but not table logic - which is exactly why validateWrite carries the rule.

3. How do you expose the field through OData and get it onto the invoice report, given both are Microsoft assets?

Read the worked answer

OData: prefer extending the existing sales order header entity over building a parallel one, so consumers keep a single contract. A data entity extension can add a field that comes from a table extension on its root table. If the mobile app only needs the header plus freight terms, a small purpose-built entity is cheaper and safer than widening a high-volume entity, since every added field is carried on every read. Either way, grant the app's role the entity privilege and read access to SalesTable - a published entity does not confer permissions.

SSRS: do not copy the report. Copying forks it permanently: Microsoft changes to the contract, the RDP class or the design will not reach the copy, and the copy must be re-diffed every update. The supported route is:

  • Extend the report's RDP contract with a field and extend the DP class via CoC (or a new temporary table field mapping) to populate it.
  • Add a new design through report extension - existing Microsoft designs cannot be modified - and select that design in a controller extension so users get it by default.
  • Redeploy the report as part of the deployable package and verify the report server deployment, not just the AOT sync.