You can use PSEvalValue in an OCL expression or EAL (action language) expression to calculate and return one value from persistent storage without loading the matching objects into memory.
What PSEvalValue does
OCLps is the subset of OCL that MDriven translates to SQL for evaluation in the database. PSEvalValue lets an OCL or EAL expression evaluate an OCLps expression and use its scalar result, such as a count or sum.
Use PSEvalValue when you need a value derived from a potentially large database set. For example, you can count asynchronous tickets that have an error without loading every SysAsyncTicket object into memory.
PSEvalValue does not subscribe to changes in the database result. This is the key trade-off: the database query can avoid loading many objects, but a changed row does not automatically update the value in the user interface.
Expression template
SomeClass.PSEvalValue(<ps-expression>, <dependon>)| Part | Meaning |
|---|---|
SomeClass
|
A class used to start the operator call. |
<ps-expression>
|
An OCLps expression that MDriven evaluates against persistent storage. It must produce the value you need. |
<dependon>
|
An expression whose change causes PSEvalValue to run again. Use this to define when the displayed value is refreshed. |
Add a database-calculated value
- Identify the value you need. For example, count tickets where
Errorhas a value. - Write the query as OCLps. Keep it within the OCLps subset; OCLps has no side effects and cannot call your methods, including methods marked
IsQuery. - Wrap the OCLps expression in
PSEvalValue. - Choose a
dependonexpression that changes whenever you want the query to run again. - Test both the returned value and its refresh behavior after database data changes.
Example: count tickets with errors
The following expression can be used in a method that has userName as a parameter:
SysAsyncTicket.PSEvalValue(
SysAsyncTicket.allInstances->select(at|at.Error.notNull)->size,
Calendar.Now
).asStringThe OCLps expression selects SysAsyncTicket rows where Error is not null and returns their count. The final .asString converts that number to a string for a string result or display context.
In the BaseApp model, Calendar.Now updates every minute. Using it as dependon therefore causes the count to be evaluated again every minute while the value is in use. Without a changing dependency, creating, updating, or deleting a matching ticket does not itself cause this PSEvalValue result to refresh.
Choose the refresh dependency deliberately
PSEvalValue does not track the objects or rows used by its OCLps expression. Do not expect the normal MDriven subscription behavior for the query result.
| Need | Depend-on approach | Example |
|---|---|---|
| Refresh at a regular interval | Use a value that changes on that interval. | Calendar.Now refreshes the ticket count every minute in BaseApp.
|
| Refresh when an input to the query changes | Use that input as the dependency. | A count filtered by a selected date can depend on the selected date value. |
| Need automatic updates when matching objects change | Consider querying the matching objects with PSEval instead, then use normal OCL on the loaded set. | For an article's liked comments, PSEval can load only comments with a like, allowing normal object subscriptions for those loaded objects. |
For a concrete comparison of counting likes in the database versus loading a filtered object set, see HowTos:OCLps Example.
Limits and performance
No result-set subscription
PSEvalValue does not fetch changes to the query result set automatically. A new row that starts matching the filter, or an existing row that stops matching it, does not update the value until dependon changes and the expression is reevaluated.
This can make PSEvalValue unsuitable where the displayed value must immediately reflect every change to the underlying objects. In that case, evaluate whether PSEval better fits the requirement.
OCLps is not all OCL
OCLps is a restricted subset of OCL designed for database evaluation. It has no side effects, cannot use model methods, and does not support tuple-returning operations such as collect and groupby. Read Documentation:OCLps before designing a complex persistent-storage expression.
Database query cost
Each reevaluation runs a database query. Add and verify the SQL Server indexes and other database performance settings needed for the filters, joins, ordering, and aggregations in your expression. A timer-based dependency can repeatedly execute the query, so use an interval and query shape appropriate for the data volume.
Always validate a new expression against known data. Confirm that the value is correct and that it performs acceptably with representative database volumes.
Select the right operator
| Requirement | Operator | Result |
|---|---|---|
| Return one database-calculated value, such as a count | PSEvalValue | A scalar value |
| Return persistent objects for further normal OCL processing | PSEval | A set of objects |
| Return multiple values as tuples | PSEvalTuples | Tuples |
| Use a SQL expression or stored procedure instead of OCLps | sqlpassthrough | SQL result or tuples, depending on the expression |
