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
- Identify the class of objects the expression must return.
- Write the database query as an OCLps expression. Keep in mind that OCLps is a subset of OCL and is translated to SQL.
- Set
maxfetchto a limit appropriate for the result you intend to show or process. - Set
offsetto0unless you are deliberately retrieving a later page. - Supply a
dependonexpression that changes when the query must be evaluated again. - 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.
