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

PSEval lets you query persistent storage with OCLps from an OCL or EAL expression and return matching objects, for developers who need to filter large database-backed sets before loading them into memory.

Use PSEval to retrieve a filtered object set

OCL normally evaluates objects that are already in memory. PSEval evaluates an OCLps expression against the database, then loads and returns the objects that match. Use it when loading a complete association or class population and filtering it in memory would be inefficient.

For example, if an article has many comments, you can use PSEval to load only comments that have a like, rather than loading every comment and filtering afterward. See HowTos:OCLps Example for that scenario.

Expression syntax

SomeClass.PSEval(<ps-expression>, <maxfetch>, <offset>, <dependon>)

Start the expression with the class whose objects PSEval must return. The <ps-expression> is evaluated as OCLps in persistent storage.

Argument Purpose Example
SomeClass The class of objects returned by PSEval. Uppdrag
<ps-expression> An OCLps expression that identifies the objects to return. u.Aktivt)
maxfetch The maximum number of objects to retrieve. 1000
offset The zero-based number of results to skip before retrieval. Use this for a later page of results. 0 for the first page
dependon An expression whose change causes PSEval to run again. self.Uppdrag

Build a PSEval expression

  1. Identify the class of objects the expression must return.
  2. Write the database query as an OCLps expression. Keep in mind that OCLps is a subset of OCL and is translated to SQL.
  3. Set maxfetch to a limit appropriate for the result you intend to show or process.
  4. Set offset to 0 unless you are deliberately retrieving a later page.
  5. Supply a dependon expression that changes when the query must be evaluated again.
  6. Run a model check and test the result and its refresh behavior with realistic data.

This example returns up to 1,000 active Uppdrag objects, ordered by descending start date:

Uppdrag.PSEval(
  self.Uppdrag->select(u|u.Aktivt)->orderDescending(u|u.Startdatum),
  1000,
  0,
  self.Uppdrag)

In this example, self.Uppdrag is also the dependency. When that expression changes, PSEval is evaluated again.

Use method parameters in the query

A PSEval expression can use variables available in the calling context. For example, a method with a userName parameter can retrieve up to two users with that user name:

SysUser.PSEval(
  SysUser.allinstances->select(su|su.Username=userName),
  2,
  0,
  '')

The empty string in the last argument means this expression has no dependency expression. It will therefore not be re-evaluated because of a changing dependency.

Understand refresh behavior

PSEval does not subscribe to the result set in the database. If an object begins to match, stops matching, or changes within the database result after PSEval has run, PSEval does not automatically fetch the changed result set. This differs from the usual framework subscription behavior for data already loaded into the ViewModel.

Use dependon to define when PSEval must run again. The dependency can be an expression that changes because of the user action or model state relevant to the query. It can also be a timer when periodic refresh is required.

For example, PSEvalValue can use Calendar.Now as a dependency so its database value is recalculated as that value updates. Apply the same principle to PSEval: choose a dependency that represents the refresh event you need.

Gotcha: A dependency only re-runs PSEval when the dependency expression changes. It does not create a database subscription. Do not expect arbitrary database updates to appear unless your dependency changes and the expression is evaluated again.

Page results with maxfetch and offset

offset is zero-based. For a paged result list with 100 objects per page:

Page maxfetch offset
First page 100 0
Second page 100 100
Third page 100 200

Keep offset at 0 unless you are implementing pagination or another deliberate later-page retrieval. Use an ordering expression when paging so that the result sequence is defined.

OCLps and inheritance limitations

PSEval uses OCLps, the persistent-storage subset of OCL. OCLps has restrictions because MDriven translates it to SQL. In particular, it has no side effects, cannot call model methods even when they are marked IsQuery, and does not support tuple-producing operations such as collect and groupby.

PSEval cannot load subclasses of a child-mapped class. To load subclasses of a superclass, use separate PSEval expressions and combine their results with union.

Validate performance and results

PSEval moves filtering to the database; it does not remove the need to design and test the database query.

  • Set a meaningful maxfetch. A high limit can still load many objects into memory.
  • Test the expression with representative database volumes.
  • Verify that the returned objects and ordering are correct.
  • Ensure that the SQL server has suitable indexes and performance settings for the generated query.
  • Re-test refresh behavior when users can change data that affects the result set.

Choose the right persistent-storage operator

Need Use
Return database-backed objects that match an OCLps filter PSEval
Return one database-calculated value, such as a count PSEvalValue
Return tuple-shaped results, such as an object together with calculated values PSEvalTuples
Execute a SQL expression or stored procedure rather than OCLps sqlpassthrough

For new development, prefer PSEval over ExecutePS.

See also