You can use a declarative ViewModel and QueryPlan to fetch the object graph a view needs in a small number of requests, and add FetchHints when a Seeker result requires additional prefetching.
How ViewModel fetching works
A ViewModel declares the data that a view uses through its nestings and expressions. MDriven can analyze that declaration before rendering the view and fetch the required objects together instead of lazily loading one object at a time.
For example, assume a root collection contains x objects, each object has y detail objects, and each detail has z related objects. Fetching each link as the UI reaches it can produce a growing number of requests. A declarative ViewModel can instead fetch the required levels as sets:
- all
xobjects; - all required
x.yobjects; - all required
x.y.zobjects.
This set-based behavior avoids the repeated lazy-fetch pattern that becomes especially costly when the application and MDrivenServer are separated by network latency.
QueryPlan is the default
QueryPlan is the standard mechanism for efficient ViewModel fetching. It statically analyzes ViewModel nestings, column expressions, and relevant model navigation to determine the types of persistent data that the view will use. It also remains active after the view is created, so it can react when a current selection changes.
In normal rooted ViewModels, you do not need to create fetch hints. QueryPlan detects the declared structure and fetches data that is not already available.
A Seeker is an unrooted ViewModel that finds objects at runtime rather than starting from one known root object. The Seeker result is commonly collected in a collection variable named vSeekerResult. Because that result does not exist when the ViewModel is initially analyzed, its downstream data can require additional handling in complex views.
When to use FetchHints
Use FetchHints only after you have measured an avoidable pattern of small fetches for objects returned by a Seeker or supplied through another runtime collection.
A FetchHints nesting is a ViewModel nesting whose name starts with FetchHints. MDriven finds these nestings and executes the columns in them for the objects in a list delivered by Seeker logic. Define the navigation and values that the UI will later need in the FetchHints nesting. This gives MDriven the information needed to fetch that related data before the UI causes individual lazy fetches.
For example, if a Seeker returns sales articles and the screen later reads each article's related details, create a nesting named FetchHintsSalesArticle and include columns that navigate to those details. The exact nesting name after the FetchHints prefix is your choice; the prefix is what identifies it as a fetch hint.
| Situation | Expected approach |
|---|---|
| A rooted ViewModel follows associations from its root. | Rely on QueryPlan. Do not add FetchHints without evidence of a problem. |
| A Seeker returns a result collection and rendering later triggers many small fetches. | Add a FetchHints... nesting describing the related data used by the result rows.
|
| Code or OCL builds a result list from another source, such as the current user's favorites. | Call selfVM.ExecuteFetchHints(theList) after building the list.
|
Diagnose excessive fetches
Measure before adding hints. A large number of fetches that each retrieve one object is a useful signal that the view is reaching data that was not fetched as a set.
- Open the Debugger.
- Go to the
Loggingtab and enablePMapperlogging. - Set an object and select the ViewModel to inspect in
Result as root for ViewModel tree. - Let the ViewModel fetch and render.
- Inspect the PMapper log for calls that fetch only one object. Note the reported
ClassIdvalues. - Look up each ClassId in the Debugger to identify the model class responsible for the fetch.
- Check whether the class is reached from a Seeker result or another list assembled after the ViewModel was loaded.
- Add the required navigation to a
FetchHints...nesting, or execute the hints explicitly for the runtime list. - Run the same scenario again and compare the PMapper log.
You can also inspect the static plan in MDriven Designer: right-click the ViewModel main class and select Extras, then QueryPlan. The report is placed on the clipboard and shows what the QueryPlan tree sees. Use it to confirm whether the ViewModel's declared nestings and expressions describe the data you expect it to fetch.
Apply hints to a list built outside a Seeker
FetchHints are automatically found for a list delivered by Seeker logic. A list constructed through other ViewModel logic does not receive that automatic treatment. Use the standard selfVM variable to execute the hints for that list.
self remains the object context in an expression. selfVM is the ViewModel instance that holds the objects. It provides these operations:
ExecuteFetchHintsexecutes the ViewModel's FetchHints for a supplied list.Saveprovides programmatic access to saving.ExecuteActionprovides programmatic access to executing an action.
The following example clears vSeekerResult, builds it from the current user's favorite articles, and then executes the ViewModel's FetchHints for that result. The collection is not a Seeker result in this path, so the final call is required to apply the same prefetch strategy.
vSeekerResult->Clear;
Singleton.oclSingleton.User.FavoriteArticle
->select(fa | fa.Filter.SqlLike(vFavFilter + '%') or vFavFilter.IsNullOrEmpty)
.FavoriteArticles
->collect(a |
let sa = a.SalesArticles
->select(sa | sa.MarketingCompany = self)
->first
in
(
if sa.isnull then
vSeekerResult
else
vSeekerResult.Add(sa)
endif
)
);
selfVM.ExecuteFetchHints(vSeekerResult)In this example, vFavFilter controls which favorites are selected. Each favorite article is mapped to its first sales article for the current marketing-company context. After the collection is complete, selfVM.ExecuteFetchHints(vSeekerResult) applies the FetchHints nesting to every result object before the UI navigates to the hinted data.
Limits and gotchas
- FetchHints address data access for a supplied collection. They do not replace a well-structured ViewModel or QueryPlan analysis.
- Do not infer a fetch problem from the total number of log entries alone. Focus on repeated single-object PMapper calls and identify their model classes before changing the ViewModel.
- QueryPlan's multi-expression fetching is a feature of MDrivenServer. The XML persistence mapper does not use that multi-expression fetcher.
- Keep FetchHints focused on data the view actually reads. Adding unrelated navigation expands the data requested for every result object.
- When a selected object from a Seeker becomes the root for detail data, QueryPlan can react through current variables and fetch the declared details. Add manual hints only for remaining measured gaps.
