Virtual Entities
A virtual entity is an entity that is not persisted to the database. It exists only at runtime and is populated by business logic. Virtual entities are useful for computed views, aggregations, and read-only result sets.
Defining a Virtual Entity
Add [Virtual] at the class level alongside [ApiEntity]:
[Virtual]
[ApiEntity]
public partial class ProductAvailability
{
[Property<DataTypes.DateOnly>("Ship date")]
public partial DateOnly? ShipDateToFilter { get; set; }
[Property<DataTypes.Integer>("Popularity Score")]
public partial int PopularityScore { get; set; }
}
Virtual Reference Properties
Virtual entities use [VirtualReferenceProperty] to reference real entities without creating foreign key columns:
[Virtual]
[ApiEntity]
public partial class ProductAvailability
{
[VirtualReferenceProperty("Breed")]
public partial Breed Breed { get; set; }
[Property<Guid>("Breed guid")]
public partial Guid BreedGuid { get; set; }
[VirtualReferenceProperty("Earliest chick type count")]
public partial ChickTypeCount EarliestChickTypeCount { get; set; }
[VirtualReferenceProperty("Matched Manufacturing orders")]
public partial List<ManufacturingOrder> MatchedManufacturingOrders { get; set; }
}
When to Use Virtual Entities
| Use Case | Example |
|---|---|
| Aggregation views | Availability summaries, dashboards |
| Computed result sets | Combined data from multiple entities |
| Read-only projections | Flattened views for reports |
| Filter/search endpoints | Parameter-driven query results |
Key Differences from Regular Entities
| Aspect | Regular Entity | Virtual Entity |
|---|---|---|
| Database table | Yes | No |
Guid primary key |
Auto-generated | Not present |
RowVersion |
Auto-tracked | Not present |
| CRUD operations | Full create/read/update/delete | Read only (see Workflows) |
| Relationships | [ReferenceProperty] with FK |
[VirtualReferenceProperty] only |
| Business logic | Events system | Custom logic populates the entity |
Workflows
A virtual entity can take part in a workflow like a regular entity. Inside the workflow you can create and edit it; changes stage in memory, stay invisible to other requests, and commit atomically when the workflow commits. No special client code is needed.
graph LR
A["Begin workflow"] --> B["Create / edit virtual entity<br/>(staged in memory)"] --> C["Commit<br/>(atomic, now visible)"]
Committed virtual entities live in the in-memory store — they are never written to a database table. See DataSet Workflows and API Workflows.
To show a virtual entity returned by a method in the UI, see Showing Method Results.