dotnet-dynamic-query/README.md

222 lines
14 KiB
Markdown
Raw Normal View History

2018-10-22 20:44:27 -04:00
# Dynamic Query
It's a library that allows you to easily query a queryable using a criteria object.
2018-10-22 20:44:58 -04:00
It also offers, to intercept the query using **IQueryInterceptor** implementations.
2018-10-22 20:44:27 -04:00
2019-03-22 17:07:13 -04:00
## Breaking Changes
If you are moving up from v1, the breaking changes details are lower.
2018-10-22 20:44:27 -04:00
## Getting Started
> Install nuget package to your awesome project.
Full Version | NuGet | NuGet Install
------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------:
PoweredSoft.DynamicQuery | <a href="https://www.nuget.org/packages/PoweredSoft.DynamicQuery/" target="_blank">[![NuGet](https://img.shields.io/nuget/v/PoweredSoft.DynamicQuery.svg?style=flat-square&label=nuget)](https://www.nuget.org/packages/PoweredSoft.DynamicQuery/)</a> | ```PM> Install-Package PoweredSoft.DynamicQuery```
PoweredSoft.DynamicQuery.Core | <a href="https://www.nuget.org/packages/PoweredSoft.DynamicQuery.Core/" target="_blank">[![NuGet](https://img.shields.io/nuget/v/PoweredSoft.DynamicQuery.Core.svg?style=flat-square&label=nuget)](https://www.nuget.org/packages/PoweredSoft.DynamicQuery.Core/)</a> | ```PM> Install-Package PoweredSoft.DynamicQuery.Core```
2018-11-18 06:48:36 -05:00
PoweredSoft.DynamicQuery.AspNetCore | <a href="https://www.nuget.org/packages/PoweredSoft.DynamicQuery.AspNetCore/" target="_blank">[![NuGet](https://img.shields.io/nuget/v/PoweredSoft.DynamicQuery.AspNetCore.svg?style=flat-square&label=nuget)](https://www.nuget.org/packages/PoweredSoft.DynamicQuery.AspNetCore/)</a> | ```PM> Install-Package PoweredSoft.DynamicQuery.AspNetCore```
2018-10-22 20:44:27 -04:00
2018-11-18 06:48:36 -05:00
## Using in ASP.NET Core
The package Asp.net core of dynamic query will help you start to use Dynamic Query faster in your web project.
### How to configure during startup
```csharp
using PoweredSoft.DynamicQuery.AspNetCore;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
2018-11-23 01:22:47 -05:00
services
.AddMvc()
.AddPoweredSoftDynamicQuery();
2018-11-18 06:48:36 -05:00
}
}
```
2018-11-18 06:51:55 -05:00
> How to use in a controller
```csharp
2018-11-18 06:53:11 -05:00
[HttpGet]
2019-03-22 17:09:44 -04:00
public IQueryExecutionResult<OfSomething> Get(
2018-11-18 06:53:11 -05:00
[FromServices]YourContext context,
[FromServices]IQueryHandler handler,
[FromServices]IQueryCriteria criteria,
int? page = null,
int? pageSize = null)
{
criteria.Page = page;
criteria.PageSize = pageSize;
IQueryable<OfSomething> query = context.Somethings;
var result = handler.Execute(query, criteria);
return result;
}
2018-11-18 06:51:55 -05:00
[HttpPost]
2019-03-22 17:09:44 -04:00
public IQueryExecutionResult<OfSomething> Read(
2018-11-18 06:51:55 -05:00
[FromServices]YourContext context,
[FromServices]IQueryHandler handler,
[FromBody]IQueryCriteria criteria)
{
IQueryable<OfSomething> query = context.Somethings;
var result = handler.Execute(query, criteria);
return result;
}
```
2018-12-07 00:25:39 -05:00
> New support for async
```csharp
[HttpPost]
2019-03-22 17:09:44 -04:00
public async Task<IQueryExecutionResult<OfSomething>> Read(
2018-12-07 00:25:39 -05:00
[FromServices]YourContext context,
[FromServices]IQueryHandlerAsync handler,
[FromBody]IQueryCriteria criteria)
{
IQueryable<OfSomething> query = context.Somethings;
var result = await handler.ExecuteAsync(query, criteria);
return result;
}
```
2018-11-18 06:48:36 -05:00
### Sample Web Project - ASP.NET CORE + EF Core
2018-11-13 17:50:50 -05:00
Visit: https://github.com/PoweredSoft/DynamicQueryAspNetCoreSample
2019-03-22 17:07:13 -04:00
### Breaking Changes if you are migrating from 1.x
Response interface, is now generic ```IQueryResult<T>``` which impacts the way to execute the handler.
#### Grouping results
Since the results are now generic, it's no longer a List<object> in the response so that changes the result if grouping is requested.
You have now a property Groups, and HasSubGroups, and SubGroups.
#### QueryConvertTo Interceptor
If you are using IQueryConvertTo interceptors, it's new that you must specify the type you are converting to
Ex:
```csharp
IQueryable<OfSomething> query = context.Somethings;
var result = handler.Execute<OfSomething, OfSomethingElse>(query, criteria);
```
2018-10-22 20:44:27 -04:00
## Criteria
Criteria must implement the following interfaces
2018-10-22 20:50:32 -04:00
2018-10-22 22:43:35 -04:00
Object | Interface | Implementation | Example | Description
-----------------|--------------------------------------------------------------------------|-------------------------------------------------------------------------------|----------------------------------------------------------------------|--------------------------------------------
2018-10-22 22:11:41 -04:00
Query Criteria | [interface](../master/PoweredSoft.DynamicQuery.Core/IQueryCriteria.cs) | [default implementation](../master/PoweredSoft.DynamicQuery/QueryCriteria.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/CriteriaTests.cs#L13) | Wraps the query parameters
2018-10-23 17:51:04 -04:00
Paging | [interface](../master/PoweredSoft.DynamicQuery.Core/IQueryCriteria.cs) | [default implementation](../master/PoweredSoft.DynamicQuery/QueryCriteria.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/CriteriaTests.cs#L29) | Paging support
2018-10-22 22:43:35 -04:00
Filter | [interface](../master/PoweredSoft.DynamicQuery.Core/IFilter.cs) | [default implementation](../master/PoweredSoft.DynamicQuery/Filter.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/FilterTests.cs#L22) | Represent a filter to be executed
Simple Filter | [interface](../master/PoweredSoft.DynamicQuery.Core/ISimpleFilter.cs) | [default implementation](../master/PoweredSoft.DynamicQuery/Filter.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/FilterTests.cs#L40) | Represent a simple filter to be executed
Composite Filter | [interface](../master/PoweredSoft.DynamicQuery.Core/ICompositeFilter.cs) | [default implementation](../master/PoweredSoft.DynamicQuery/Filter.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/FilterTests.cs#L68) | Represent a composite filter to be executed
2018-10-22 22:45:35 -04:00
Sort | [interface](../master/PoweredSoft.DynamicQuery.Core/ISort.cs) | [default implementation](../master/PoweredSoft.DynamicQuery/Sort.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/SortTests.cs#L15) | Represent a sort to be executed
2018-10-22 23:58:58 -04:00
Group | [interface](../master/PoweredSoft.DynamicQuery.Core/IGroup.cs) | [default implementation](../master/PoweredSoft.DynamicQuery/Group.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/GroupTests.cs) | Represent a group to be executed
2018-10-23 17:51:04 -04:00
Aggregate | [interface](../master/PoweredSoft.DynamicQuery.Core/IAggregate.cs) | [default implementation](../master/PoweredSoft.DynamicQuery/Aggregate.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/AggregateTests.cs) | Represent an aggregate to be executed
2018-10-22 20:44:27 -04:00
### Sample
```csharp
var criteria = new QueryCriteria
{
Page = 1,
PageSize = 12,
Filters = new List<IFilter>
{
new SimpleFilter { Path = "FirstName", Type = FilterType.Equal, Value = "John" }
}
};
var queryHandler = new QueryHandler();
2019-03-22 17:09:44 -04:00
IQueryExecutionResult<OfSomeQueryableType> result = queryHandler.Execute(someQueryable, criteria);
2018-10-22 20:44:27 -04:00
```
## Query Result
Here is the interfaces that represent the result of query handling execution.
2019-03-22 17:09:44 -04:00
> Changed in 2.x
2018-10-22 20:44:27 -04:00
```csharp
public interface IAggregateResult
{
string Path { get; set; }
AggregateType Type { get; set; }
object Value { get; set; }
}
2019-03-22 17:09:44 -04:00
public interface IQueryResult<TRecord>
2018-10-22 20:44:27 -04:00
{
List<IAggregateResult> Aggregates { get; }
2019-03-22 17:09:44 -04:00
List<TRecord> Data { get; }
2018-10-22 20:44:27 -04:00
}
2019-03-22 17:09:44 -04:00
public interface IGroupQueryResult<TRecord> : IQueryResult<TRecord>
2018-10-22 20:44:27 -04:00
{
string GroupPath { get; set; }
object GroupValue { get; set; }
2019-03-22 17:09:44 -04:00
bool HasSubGroups { get; }
List<IGroupQueryResult<TRecord>> SubGroups { get; set; }
2018-10-22 20:44:27 -04:00
}
2019-03-22 17:09:44 -04:00
public interface IQueryExecutionResultPaging
2018-10-22 20:44:27 -04:00
{
long TotalRecords { get; set; }
long? NumberOfPages { get; set; }
}
2019-03-22 17:09:44 -04:00
public interface IQueryExecutionResult<TRecord> : IQueryResult<TRecord>, IQueryExecutionResultPaging
{
}
public interface IQueryExecutionGroupResult<TRecord> : IQueryExecutionResult<TRecord>
{
List<IGroupQueryResult<TRecord>> Groups { get; set; }
}
2018-10-22 20:44:27 -04:00
```
## Interceptors
2018-10-22 22:44:27 -04:00
Interceptors are meant to add hooks at certain part of the query handling to allow alteration of the criterias or the queryable it self.
2018-10-22 20:44:27 -04:00
The following is documented in the order of what they are called by the **default** query handler implementation.
> Before the expression is being built
Interceptor | Interface | Example | Description
---------------------------------------|--------------------------------------------------------------------------------------------|-------------------------------------------------------------|------------------------------------------------------------------------------------------------------------
2018-10-23 18:08:32 -04:00
IIncludeStrategyInterceptor | [interface](../master/PoweredSoft.DynamicQuery.Core/IIncludeStrategyInterceptor.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/IncludeStrategyTests.cs) | This is to allow you to specify include paths for the queryable
IIncludeStrategyInterceptor&lt;T&gt; | [interface](../master/PoweredSoft.DynamicQuery.Core/IIncludeStrategyInterceptor.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/IncludeStrategyTests.cs#L65) | This is to allow you to specify include paths for the queryable
2018-10-23 18:21:01 -04:00
IBeforeQueryFilterInterceptor | [interface](../master/PoweredSoft.DynamicQuery.Core/IBeforeQueryFilterInterceptor.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/BeforeFilterTests.cs) | Before adding the filters to the expression
IBeforeQueryFilterInterceptor&lt;T&gt; | [interface](../master/PoweredSoft.DynamicQuery.Core/IBeforeQueryFilterInterceptor.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/BeforeFilterTests.cs#L64) | Before adding the filters to the expression
INoSortInterceptor | [interface](../master/PoweredSoft.DynamicQuery.Core/INoSortInterceptor.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/NoSortTests.cs) | This is called to allow you to specify an OrderBy in case none is specified, to avoid paging crash with EF6
INoSortInterceptor&lt;T&gt; | [interface](../master/PoweredSoft.DynamicQuery.Core/INoSortInterceptor.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/NoSortTests.cs#L65) | This is called to allow you to specify an OrderBy in case none is specified, to avoid paging crash with EF6
2018-10-22 20:44:27 -04:00
> After/During expression building before query execution
Interceptor | Interface | Example | Description
----------------------|------------------------------------------------------------------------------------|-------------------------------------------------------------|---------------------------------------------------------------------------------------------------
2018-10-23 22:07:39 -04:00
IFilterInterceptor | [interface](../master/PoweredSoft.DynamicQuery.Core/IFilterInterceptor.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/FilterInterceptorTests.cs) | This interceptor allows you to change the behavior of a IFilter being applied to the queryable
ISortInterceptor | [interface](../master/PoweredSoft.DynamicQuery.Core/ISortInterceptor.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/SortInterceptorTests.cs) | This interceptor allows you to change the behavior of a ISort being applied to the queryable
2018-10-23 22:38:28 -04:00
IGroupInterceptor | [interface](../master/PoweredSoft.DynamicQuery.Core/IGroupInterceptor.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/GroupInterceptorTests.cs) | This interceptor allows you to change the behavior of a IGroup being applied to the queryable
IAggregateInterceptor | [interface](../master/PoweredSoft.DynamicQuery.Core/IAggregateInterceptor.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/AggregateInterceptorTests.cs) | This interceptor allows you to change the behavior of a IAggregate being applied to the queryable
2018-10-22 20:44:27 -04:00
> Post Query execution
Interceptor | Interface | Example | Description
----------------------------------|---------------------------------------------------------------------------------------|-------------------------------------------------------------|------------------------------------------------------------------------------------------------
2018-10-23 23:14:18 -04:00
IQueryConvertInterceptor | [interface](../master/PoweredSoft.DynamicQuery.Core/IQueryConvertInterceptor.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/ConvertibleInterceptorTests.cs) | This interceptor allows you to replace the object that is being returned by the query, by another object instance
2018-11-18 06:51:55 -05:00
IQueryConvertInterceptor&lt;T&gt; | [interface](../master/PoweredSoft.DynamicQuery.Core/IQueryConvertInterceptor.cs) | [test](../master/PoweredSoft.DynamicQuery.Test/ConvertibleInterceptorTests.cs#L72) | This interceptor allows you to replace the object that is being returned by the query, by another object instance