Query Language & Data Retrieval
PlayServ uses a LINQ-like syntax to provide IDE highlighting and suggestions. Data filtering is supported, and nested relations are expanded automatically according to the data schema.
Retrieve a single object by key
When you need a specific object, use selection by key.
var player = await PlayServ.Model<Player>()
.Key(playerId)
.With(p => p.InventoryItems.Price < 500)
.With(p => p.InventoryItems.Creator.Race == "Gnome");
// sugar
var player = await PlayServ.GetPlayer(playerId);
Retrieve a collection
For collections, use Where(...), and use With(...) for nested blocks when required.
var players = await PlayServ.Model<Player>()
.Where(player => player.Age > 15)
.With(p => p.InventoryItems.Price < 500);
A shortened sugar form is available for collections:
var players = await PlayServ.GetPlayers(
[ p => p.Age > 15 ],
[ p => p.InventoryItems.Price < 500 ]
);
// C# 12 / .NET 8
Where vs With: separation of responsibilities
Whererestricts which objects are selected into the result.Withfilters nested data blocks within the selected objects.
This separation is reflected directly in the server-side query form.
Server-side query translation and data volume
Two rules apply when a query is executed:
- The query is translated into a server-side form — see the example below.
- The set of requested fields depends on which data is read in code.
Not all fields are requested automatically. The code analyser detects which fields are read and builds the server request accordingly — other fields remain NULL.
A field may remain NULL if it was not included in the query shape. This behaviour is tied to which fields are read in code.
Working with multiple models and expanding relations
The query language supports working with multiple models and automatically expands nested relations based on the schema.
Example of describing relations between models:
Player {
InventoryItems = InventoryItem {
Creator = Player
}
Clan = Clan {
King = Player
}
}
Model extensions at any nesting depth
If a model has special extensions, they apply regardless of the nesting level at which the model is obtained.
player.InventoryItems[3].Creator.Trade();
Condition constraint: Expression only
A handler passed to Where or With must be an Expression. Use Expression<Func<T,bool>> in the query interface.
Where and With require code analysis that builds a DSL query from the condition and blocks unsupported instructions.
Server-side query form
The LINQ-style query is translated into a server-side form. Where conditions restrict object selection, while With conditions filter nested data:
Player(where: {
Age: {_gt: 15}
Clan: { King: { Age: {_gt: 25}}}
}) {
Name
Age
InventoryItems(where: {Price: {_lt: 500}}) {
Name
Creator(where: {Race: {_eq: "Gnome"}}) {
Name
Race
}
}
Clan {
Name
King {
Name
Age
}
}
}
Next step
Continue with Data Subscriptions & Live Updates to understand how to subscribe to live data changes.
For related topics:
- Data Subscriptions & Live Updates — query subscriptions,
Wait<Update>,Stop() - Data Mutation & Model Extending —
Update()/Delete()and extending models with methods