Custom Mediator Requests: Queries
In BlazorForKids, you can define custom data-retrieval logic using a powerful and minimalistic approach called Custom Mediator Queries. These queries allow you to create read-only projections from your entities in a clean and structured way — ideal for building custom reports, views, lists, or filtered data sets.
A custom query is built around the IBkProjectFromEntity<TSelf, TEntity, TDbContext>
interface,
and the only requirement is that you provide a static LINQ projection that tells the framework how to map from the entity to your view model.
When to Use a Custom Query
Use custom queries when you want to:
- Retrieve a specific set of data that doesn’t fit the default edit or display models.
- Display computed, aggregated, or flattened values from an entity.
- Expose specific fields of an entity without loading the full model.
- Build a report or dashboard from one or more related tables (with joins).
These queries are read-only and designed for performance. They are perfect for dashboards, filtered tables, and API-like reads.
How to Define a Custom Query
To define a custom query, follow these steps:
- Create a class that represents the output model — i.e., the shape of the data you want to return.
-
Implement the
IBkProjectFromEntity<TSelf, TEntity, TDbContext>
interface on that class. -
Implement the required static property
ProjectFromEntity
which defines how to map from the entity to your class.
Interface Signature
publicinterfaceIBkProjectFromEntity<TSelf,TEntity,TDbContext>:IBkProjectFromEntityBase<TSelf,TEntity>whereTEntity:class,IBkEntity<TEntity,TDbContext>whereTDbContext:DbContext
{
staticabstractExpression<Func<TEntity,TSelf>>ProjectFromEntity{get;}
}
Example: Projecting Employee Task Info
publicclassProjectTeamMemberTasksInfo:IBkProjectFromEntity<ProjectTeamMemberTasksInfo,Employee,ApplicationDbContext>
{
publicstringFirstName{get;set;}
publicstringLastName{get;set;}
publicintTotalTasks{get;set;}
publicstaticExpression<Func<Employee,ProjectTeamMemberTasksInfo>>ProjectFromEntity=>employee=>newProjectTeamMemberTasksInfo()
{
FirstName=employee.FirstName,
LastName=employee.LastName,
TotalTasks=employee.Tasks.Count
};
}
What the Framework Does for You
Once the class implements IBkProjectFromEntity
and provides the ProjectFromEntity
mapping:
- The framework will automatically generate a mediator request handler class for your query.
- The generated handler will apply filters (if any) and return paginated results using the provided projection.
-
The query method will be added automatically to the
IBkMediatorDomain
interface. -
A concrete implementation will be available in
BkMediatorDomain
— ready to be injected and used.
Generated Method in IBkMediatorDomain
publicpartialinterfaceIBkMediatorDomain
{
Task<BkPaginationQueryResult<ProjectTeamMemberTasksInfo>>QueryProjectTeamMemberTasksInfo(BkFilterCollection<Employee>?filters=null,CancellationTokencancellationToken=default);
}
Generated Implementation
publicclassBkMediatorDomain
{
publicTask<BkPaginationQueryResult<ProjectTeamMemberTasksInfo>>QueryProjectTeamMemberTasksInfo(BkFilterCollection<Employee>?filters=null,CancellationTokencancellationToken=default)
{
returndispatcher.Send<QueryProjectTeamMemberTasksInfo
BkPaginationQueryResult<ProjectTeamMemberTasksInfo>>>(newQueryProjectTeamMemberTasksInfo(filters),cancellationToken);
}
}
How to Use a Custom Query
Anywhere in your application, simply inject the IBkMediatorDomain
interface and call your generated method.
publicclassDashboardService(IBkMediatorDomainmediator)
{
publicasyncTaskLoadDataAsync()
{
// create a filter collection for the Employee entity varfilters=newBkFilterCollection<Employee>();
// add filters filters.AddDefaultFilter(a=>a.Tasks.Any());
filters.AddDefaultFilter(a=>a.IsActive);
// sort the collection filters.AddOrderBy(a=>a.LastName,BkSortDirection.Ascending);
// set the page size filters.Paginator.SetPageSize(10);
// call the mediator to get the data varresult=awaitmediator.QueryProjectTeamMemberTasksInfo(filters);
List<ProjectTeamMemberTasksInfo>teamMembers=result.Items;
// use the data for your needs }
}
Naming Convention
To keep things consistent, the framework automatically names the generated query request with a Query
prefix.
-
If your class is named
ProjectTeamMemberTasksInfo
, the request will be registered asQueryProjectTeamMemberTasksInfo
. - This naming is used for both DI registration and mediator request invocation.
Summary
Custom Queries are a fast, reliable, and scalable way to retrieve structured, filtered, and projected data in BlazorForKids. You only need to write the projection — the framework does the rest: registration, DI, handler generation, pagination, and filtering.
- Lightweight and fast
- Fully typed and compile-safe
- Automatically integrated into the mediator domain
- Excellent for lists, tables, dashboards, and read-only views