-
Notifications
You must be signed in to change notification settings - Fork 0
iii. Query Class
The purpose of a query class is to execute with supported QueryEngine to fetch data from data storage.
- QueryEngine is an implementation of
IQueryEngine
to execute queries against a supported data storage to return a collection of query results (ie. of type IQueryResult).
As explained above, You can configure a query in Parent
or Child
(nested) mode in nested hierarchies.
To define a parent
or root
query which is usually configured at level 1 to query the root entity, derive from aseRootQuery<TQueryParameter, TQueryResult>
-
TQueryParameter
is basically the class that holds theinputs
required by the root query for execution. It is an implementation ofIQueryParameter
type. -
TQueryResult
is the result that will be returned from executing the root query. It is an implementation ofIQueryResult
type.
The query parameter needs to be resolved before executing the query with QueryEngine.
In parent
mode, the query parameter is resolved using the IDataContext
parameter passed to data provider class.
See example
CustomerQuery
implemented to be configured and run in parent mode below.internal class CustomerQuery : BaseRootQuery<CustomerParameter, CustomerResult> { public override void ResolveRootQueryParameter(IDataContext context) { // Executes as Parent or Level 1 query. // The query parameter is resolved using IDataContext parameter of data provider class. var customer = (CustomerContext)context; QueryParameter = new CustomerParameter { CustomerId = customer.CustomerId }; } }
To define a child
or dependant
query which is usually configured as child at level below the root query to query, derive from BaseChildQuery<TQueryParameter, TQueryResult>
-
TQueryParameter
is basically the class that holds theinputs
required by the child query for execution. It is an implementation ofIQueryParameter
type. -
TQueryResult
is the result that will be returned by executing the child query. It is an implementation ofIQueryResult
type.
Similar to Root query, the query parameter of child query needs to be resolved before executing with QueryEngine.
In child
mode, the query parameter is resolved using the query result
of the parent
query. You can have a maximum of 5
levels of query nestings.
See example
CustomerCommunicationQuery
implemented to be configured and run as child or nested query to customer query below. Please seeCustomerSchema
definition above for parent/child configuration setup.internal class CustomerCommunicationQuery : BaseChildQuery<CustomerParameter, CommunicationResult> { public override void ResolveChildQueryParameter(IDataContext context, IQueryResult parentQueryResult) { // Execute as child to customer query. // The result from parent customer query is used to resolve the query parameter of the nested communication query. var customer = (CustomerResult)parentQueryResult; QueryParameter = new CustomerParameter { CustomerId = customer.Id }; } }
Please Note:
The above query implementation examples are with respect to parent/child configuration. The actual storage specific query definition should vary with specific implementation of the QueryEngine.
Please see supported Query engine implementations below.
-
Schemio.SQL
- provides the implementation of IQueryEngine to execute SQL queries. UsesDapper
for SQL data acess. -
Schemio.EntityFramework
- provides implementation of IQueryEngine to executeEntity Framework
queries.
The SQL query needs to implement BaseSQLRootQuery<TQueryParameter, TQueryResult>
or BaseSQLChildQuery<TQueryParameter, TQueryResult>
based on parent or child implementation.
And, requires implementing public abstract CommandDefinition GetCommandDefinition()
method to return command definition
for query to be executed with Dapper
supported QueryEngine.
See below example CustomerQuery
implemented as Root SQL query
internal class CustomerQuery : BaseSQLRootQuery<CustomerParameter, CustomerResult> { public override void ResolveRootQueryParameter(IDataContext context) { // Executes as root or level 1 query. var customer = (CustomerContext)context.Entity; QueryParameter = new CustomerParameter { CustomerId = (int)customer.CustomerId }; } public override IEnumerable<CustomerResult> Execute(IDbConnection conn) { return conn.Query<CustomerResult>(new CommandDefinition ( "select CustomerId as Id, " + "Customer_Name as Name," + "Customer_Code as Code " + $"from TCustomer where customerId={QueryParameter.CustomerId}" )); } }
See below example CustomerOrderItemsQuery
implemented as child SQL query.
internal class CustomerOrderItemsQuery : BaseSQLChildQuery<OrderItemParameter, OrderItemResult> { public override void ResolveChildQueryParameter(IDataContext context, IQueryResult parentQueryResult) { // Execute as child query to order query taking OrderResult to resolve query parameter. var ordersResult = (OrderResult)parentQueryResult; QueryParameter ??= new OrderItemParameter(); QueryParameter.OrderIds.Add(ordersResult.OrderId); } public override IEnumerable<OrderItemResult> Execute(IDbConnection conn) { return conn.Query<OrderItemResult>(new CommandDefinition ( "select OrderId, " + "OrderItemId as ItemId, " + "Name, " + "Cost " + $"from TOrderItem where OrderId in ({QueryParameter.ToCsv()})" )); } }
The SQL query needs to implement BaseSQLRootQuery<TQueryParameter, TQueryResult>
or BaseSQLChildQuery<TQueryParameter, TQueryResult>
based on parent or child implementation.
And, requires implementing public abstract IEnumerable<IQueryResult> Run(DbContext dbContext)
method to implement query using DbContext
using entity framework.
See below example CustomerQuery
implemented as Root Entity framework query
internal class CustomerQuery : BaseSQLRootQuery<CustomerParameter, CustomerResult> { public override void ResolveRootQueryParameter(IDataContext context) { // Executes as root or level 1 query. var customer = (CustomerContext)context.Entity; QueryParameter = new CustomerParameter { CustomerId = (int)customer.CustomerId }; } public override IEnumerable<IQueryResult> Run(DbContext dbContext) { return dbContext.Set<Customer>() .Where(c => c.Id == QueryParameter.CustomerId) .Select(c => new CustomerResult { Id = c.Id, Name = c.Name, Code = c.Code }); } }
See below example CustomerOrderItemsQuery
implemented as child Entity framework query.
internal class CustomerOrderItemsQuery : BaseSQLChildQuery<OrderItemParameter, OrderItemResult> { public override void ResolveChildQueryParameter(IDataContext context, IQueryResult parentQueryResult) { // Execute as child query to order query taking OrderResult to resolve query parameter. var ordersResult = (CustomerOrderResult)parentQueryResult; QueryParameter ??= new OrderItemParameter(); QueryParameter.OrderIds.Add(ordersResult.OrderId); } public override IEnumerable<IQueryResult> Run(DbContext dbContext) { return dbContext.Set<OrderItem>() .Where(p => QueryParameter.OrderIds.Contains(p.Order.OrderId)) .Select(c => new OrderItemResult { ItemId = c.ItemId, Name = c.Name, Cost = c.Cost, OrderId = c.Order.OrderId }); ; } }