🚀 Welcome to MDriven Learn –  MDriven is now on Discord!  Don’t miss the latest Release Notes.
OCLOperators PSEvalTuples
This page was created by Hans.karlsen on 2023-06-05. Last edited by Wikiadmin on 2026-07-29.

You can use PSEvalTuples in OCL and action language (EAL) when you need the database to evaluate an OCL expression and return calculated rows as tuples.

What PSEvalTuples does

PSEvalTuples evaluates an OCL persistence-server expression (oclPS) against the database. Use it when the result is not a set of one modeled object type, but a row made from several values, such as an object, a related object, and an aggregate.

For example, you can return one row containing an assignment, its consultant, and the sum of reported hours. The result is a collection of tuples; tuple parts are exposed as Part1, Part2, and so on.

Expression syntax

SomeClass.PSEvalTuples(<ps-expression>, maxfetch, offset, <dependon>)
Parameter Purpose Example
SomeClass The class that starts the expression. Consultant
<ps-expression> The OCL expression to evaluate in the database. Use ->collect to construct tuple rows. a,a.Consultant)
maxfetch The maximum number of rows to fetch. 100
offset The zero-based starting offset. Use 0 unless you are fetching a later page of results. 0
<dependon> An expression whose change causes PSEvalTuples to run again. vTheStartDate

Create a tuple query

  1. Start with the class from which the database query should begin.
  2. Write the persistence-server OCL expression that selects, navigates, and calculates the required data.
  3. Use ->collect with comma-separated values to create each tuple row.
  4. Set maxfetch to a limit appropriate for the UI or operation.
  5. Use offset 0 for the first result page.
  6. Supply a dependency expression that changes whenever the query must be reevaluated.

The following expression finds active assignments for consultants, sums billed hours reported after vTheStartDate, and returns tuples:

Consultant.PSEvalTuples(
  self.Assignments->select(a|a.Active)->collect(
    a|a,
      a.Consultant,
      a.BilledHours->select(bh|bh.WorkDate>vTheStartDate).Hours->sum
  ),
  100,
  0,
  vTheStartDate
)

Each returned tuple has these parts:

Tuple part Value in the example
Part1 The assignment (a)
Part2 The assignment's consultant (a.Consultant)
Part3 The sum of qualifying billed-hour values

See Documentation:Tuple for how tuple results are structured and accessed.

Make the result refresh when it must

PSEvalTuples does not subscribe to the database set that it reads. A database change to an assignment or billed-hour record does not, by itself, update the result in your ViewModel.

Use dependon to declare what should trigger a new evaluation. In the example above, changing vTheStartDate reevaluates the query, so the returned totals use the new date.

If you need periodic refresh, use an expression that changes periodically, such as a timer value. Ensure that the dependency represents every change that should cause the displayed result to be recalculated. Without an appropriate dependency, the result can remain stale even though the database data has changed.

Aggregation limitation

OCL can express queries that cannot always be translated to equivalent SQL. In particular, do not rely on multiple independent aggregates in the same collected tuple when each aggregate is calculated from a different filtered set.

For example, this pattern can return incorrect values:

->collect(x|x,
  x.Name,
  x.Something->select(goodone).Value->sum,
  x.Something->select(badone).Value->sum
)

Split the calculation so that each expression performs one aggregation, then combine the results in a way appropriate for your model and ViewModel. Test every new aggregate expression against known data and verify the returned numbers before using it in production.

Performance and paging

PSEvalTuples runs work in the SQL database. Add and maintain the database indexes and SQL Server performance settings needed by the filters, joins, sorting, and aggregation in your expression.

Keep maxfetch bounded. Use a nonzero offset only when implementing paging or another deliberate later-page fetch; offset is zero-based.

Choose the right operator

Need Operator
A database-evaluated result containing tuple rows PSEvalTuples
A database-evaluated set of objects PSEval
One database-evaluated scalar value, such as a count PSEvalValue
A direct SQL expression or stored-procedure call sqlpassthrough

See also