✏️ Explanatory Question

Walk through building an Extensible Data Security (XDS) policy end-to-end. What are the components (primary/constrained tables, policy query, context), how do you set a context in X++, and what performance considerations apply?

👁 2 Views
📘 Detailed Answer
🟢 Easy
💡

Answer with Explanation

D365 F&O • X++ INTERVIEW

Building an XDS (Extensible Data Security) Policy End-to-End in Dynamics 365 Finance & Operations

Question 59 — Row-level security with a constrained table, policy query and context.

Interview Question

Walk through building an Extensible Data Security (XDS) policy end-to-end. What are the components (primary/constrained tables, policy query, context), how do you set a context in X++, and what performance considerations apply?

Model Answer (Short)

XDS enforces row-level security by silently adding a filter to every query against a constrained table. To build one you create a security policy object with four key parts: the primary table (the table that drives the restriction, e.g. a worker-to-business-unit mapping), a policy query (built on the primary table, defining which rows are allowed), the constrained table(s) (the tables the filter is applied to), and the context (how the policy is triggered — by role or by application context value). At runtime the framework joins the policy query into every read of the constrained table so users only see permitted rows. Because it adds a join to every query, you must design the primary↔constrained relationship carefully and ensure the fields are indexed to protect performance.

The Four Components

Policy building blocks

  • Primary table — the table that determines the constraint (e.g. maps a user/worker to a business unit).
  • Policy query — a query on the primary table defining the allowed rows.
  • Constrained table(s) — the tables the row filter is enforced on.
  • Context — how the policy applies: RoleContext, ContextString (application context), or RoleName.
HOW IT WORKS
Policy query on primaryjoined into every read of constrained tableuser sees allowed rows only

Context types

  • RoleContextType — the policy applies to users assigned specific security roles.
  • ContextString — the policy applies based on an application context value set in X++.
  • RoleName — the policy is tied to one named role.

End-to-End Build Steps

StepAction
1Create the primary table (or reuse one) that drives the constraint
2Build a query on the primary table for the allowed rows
3Create a Security Policy object; set PrimaryTable & Query
4Add the constrained table(s) and the relation to the primary
5Set the ContextType (Role / ContextString) and enable the policy
6Set the context in X++ if using ContextString

Prerequisites (Rule 5)

  • Visual Studio with the Dynamics 365 developer tools.
  • A custom model / package for your objects.
  • A primary table and a query defining the allowed rows.
  • Indexes on the primary↔constrained relation fields.

Code Example — Setting the application context (ContextString)

// When the policy uses ContextType = ContextString, set the context in X++
XDSServices xdsServices = new XDSServices();

// The policy's context string must match what you set here
xdsServices.setXDSContext(
    curUserId(),
    "BusinessUnitContext");   // matches the policy ContextString

// Now any query on the constrained table is filtered for this context.

Policy query concept (primary table)

// Conceptual: the policy query on the primary table (AbcWorkerBusinessUnit)
// returns the business units the CURRENT user is allowed to see.
// The framework joins this into every read of the constrained table
// (e.g. AbcOrderHeader) on BusinessUnitId.
//
//   AbcWorkerBusinessUnit.WorkerId == currentWorker
//   AbcWorkerBusinessUnit.BusinessUnitId == AbcOrderHeader.BusinessUnitId

Effect on a normal select (transparent filtering)

AbcOrderHeader header;

// The developer writes a normal select — XDS silently adds the
// policy filter so only permitted business units are returned.
while select header
{
    info(header.OrderId);   // only allowed rows appear
}

Performance considerations

  • Every read of the constrained table gets an extra join to the policy query.
  • Ensure the primary↔constrained relation fields are indexed.
  • Keep the policy query simple — avoid heavy joins inside it.
  • Test with realistic data volumes; XDS can affect query plans.

Points the interviewer wants to hear

  • XDS enforces row-level security by joining a policy query into reads.
  • Four parts: primary table, policy query, constrained table(s), context.
  • Context is Role-based or ContextString (set via XDSServices).
  • Filtering is transparent — developers write normal selects.
  • Index the relation and keep the policy query lean for performance.

Likely Follow-up Questions

  • What are the four components of an XDS policy?
  • What is the difference between a Role context and a ContextString?
  • How does XDS affect a normal select statement?
  • What performance precautions do you take with XDS policies?

Key Takeaway

An XDS policy adds transparent row-level security by joining a policy query (on a primary table) into every read of the constrained table, triggered by a role or ContextString. Design the relationship and indexes carefully, because the added join affects performance on every query.