Skip to content

QuickStart

MisterHoker edited this page Apr 13, 2021 · 7 revisions

Quick Start with AspNetCore + EntityFrameworkCore

Discover how to build AspNetCore applications with dynamic EntityFramework queries with this Quick Start guide.

Example application

All information mentioned above could be found in Example Application.
The source code of Example Application located in the QueryNinja repo. Also, Example application is public and can be discovered via THIS LINK.

Install packages

In order to make everything these packages are required: dotnet add package QueryNinja.Sources.AspNetCore --version 1.1.0 dotnet add package QueryNinja.Targets.EntityFrameworkCore --version 1.1.0 dotnet add package QueryNinja.Core --version 1.1.0

Also, we have a swagger extension: dotnet add package QueryNinja.Extensions.AspNetCore.Swagger --version 1.1.0 This extension will be reviewed later in this article.

Modify exisitng application

AspNetCore Startup

Register QueryNinja to the IServiceCollection.

using QueryNinja.Sources.AspNetCore;
using QueryNinja.Targets.EntityFrameworkCore;
---
services
    .AddQueryNinja()
    .WithEntityFrameworkTarget();

This is how Swagger extension should be enabled:

using QueryNinja.Extensions.AspNetCore.Swagger;
---
services.AddSwaggerGen(options =>
{
    options.WithQueryNinja();
}); 

AspNetCore Controller

To the controller action method add a parameter of type IQuery and [FromQuery] attribure.

Example:

using QueryNinja.Core;
---
public async Task<IEnumerable<dynamic>> Get([FromQuery] IDynamicQuery query)

Database calling code

Append query to prepared IQueryable instance:

using QueryNinja.Targets.Queryable;
---
var result = await dbContext.Students
    .AsNoTracking()
    .Include(student => student.Grades)
    .ThenInclude(grade => grade.Exam)
    .WithQuery(query) //IQuery query
    .ToListAsync()

Test queries

Filter

Now you are ready to test application.

Here is the list of avaiable filters:

  • Equals
  • NotEquals
  • Greater
  • GreaterOrEquals
  • Less
  • LessOrEquals
  • Contains
  • IsEmpty

You can use this filter inside a query string: ?filter.PropertyName.Equals=value.

Example: https://query-ninja.herokuapp.com/Students?filter.Name.Equals=Dina%20Davies
Will return students with Name Dina Davies.

Sort

You can sort your data using query string: ?order.PropertyName=Ascending or ?order.PropertyName=Descending.

Example: https://query-ninja.herokuapp.com/Students?order.Name=Ascending
Will return students ordered by Name.
Multiple order parameters will result in nested ordering.

Projection

For IDynamicQuery you can define projections that will be translated into Select expressions:

  • ?select=Id - will select only Id property.
  • ?select.Grades.Count=GradesCount - will select count of Grades into GradesCount property.

Example: https://query-ninja.herokuapp.com/Students?select=Id&select.Grades.Count=GradesCount
Will return array of students with only two fields: Id and GradesCount.

Benchmarks

There are 3 processes covered with Benchmarks now:

  • ModelBinding
  • Appending IDynamicQuery to IQueryable instance
  • Performance comparison for each particular QueryBuilder

Model Binding

Scenarios description:

  • 10 Filters - 10 query params corresponding to IDefaultFilter
  • 10 Ordering Rules - 10 query params corresponding to OrderingRule
  • 10 Selects - 10 query params corresponding to ISelector
  • 10 of Each - 30 query params. All of the above.
  • EmptyQuery - no Query params.
BenchmarkDotNet=v0.12.1, OS=alpine 3.13 (container)
Intel Xeon CPU E5-2673 v4 2.30GHz, 1 CPU, 2 logical and 2 physical cores
.NET Core SDK=5.0.202
  [Host]     : .NET Core 5.0.5 (CoreCLR 5.0.521.16609, CoreFX 5.0.521.16609), X64 RyuJIT
  Job-DZCMFO : .NET Core 5.0.5 (CoreCLR 5.0.521.16609, CoreFX 5.0.521.16609), X64 RyuJIT

MaxIterationCount=30  
Method Scenario Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated
ModelBinding 10 Filters 23.79 μs 0.586 μs 0.858 μs 0.1831 0.0916 - 5.39 KB
ModelBinding 10 OrderingRules 22.48 μs 0.720 μs 1.078 μs 0.1526 0.0916 - 4.55 KB
ModelBinding 10 Selects 18.13 μs 0.902 μs 1.322 μs 0.1526 0.0610 - 4.25 KB
ModelBinding 10 of Each 42.58 μs 1.648 μs 2.467 μs 0.4272 0.2441 0.0610 9.41 KB
ModelBinding Empty Query 11.98 μs 0.663 μs 0.992 μs 0.0916 0.0458 0.0153 2.27 KB

Appending IDynamicQuery to IQueryable instance

Scenarios description:

  • 5 Filters - 5 IDefaultFilter components.
  • 5 Ordering Rules - 5 OrderingRule components.
  • 5 Selects - 5 ISelector components.
  • 5 of Each - 15 query params. All of the above.
  • EmptyQuery - no QueryComponents.
BenchmarkDotNet=v0.12.1, OS=alpine 3.13 (container)
Intel Xeon CPU E5-2673 v4 2.30GHz, 1 CPU, 2 logical and 2 physical cores
.NET Core SDK=5.0.202
  [Host]     : .NET Core 5.0.5 (CoreCLR 5.0.521.16609, CoreFX 5.0.521.16609), X64 RyuJIT
  Job-DZCMFO : .NET Core 5.0.5 (CoreCLR 5.0.521.16609, CoreFX 5.0.521.16609), X64 RyuJIT

MaxIterationCount=30  
Method Scenario Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated
Query 5 Filters 37.279 μs 0.7264 μs 1.0647 μs 0.3052 - - 9457 B
Query 5 Order Rules 30.870 μs 0.6058 μs 0.8492 μs 0.3357 - - 9480 B
Query 5 Selects 19.578 μs 0.3799 μs 0.4666 μs 0.2441 - - 6720 B
Query 5 of Each 87.741 μs 1.7088 μs 1.8284 μs 0.8545 - - 23099 B
Query Empty Query 3.299 μs 0.0641 μs 0.0856 μs 0.0343 - - 984 B

Performance comparison for each particular QueryBuilder

Scenarios description:

  • Collection Filter - time needed to append 1 CollectionFilter to IQueryable.
  • Comparison Filter - time needed to append 1 ComparisonFilter to IQueryable.
  • Default Filter - time needed to append 1 customly defined IDefaultFilter to IQueryable.
  • Ordering Rule - time needed to append 1 OrderingRule to IQueryable.
BenchmarkDotNet=v0.12.1, OS=alpine 3.13 (container)
Intel Xeon CPU E5-2673 v4 2.30GHz, 1 CPU, 2 logical and 2 physical cores
.NET Core SDK=5.0.202
  [Host]     : .NET Core 5.0.5 (CoreCLR 5.0.521.16609, CoreFX 5.0.521.16609), X64 RyuJIT
  Job-DZCMFO : .NET Core 5.0.5 (CoreCLR 5.0.521.16609, CoreFX 5.0.521.16609), X64 RyuJIT

MaxIterationCount=30  
Method Scenario Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated
QueryBuilding Collection Filter 6.694 μs 0.1305 μs 0.1282 μs 0.0687 - - 1.83 KB
QueryBuilding Comparison Filter 4.543 μs 0.0881 μs 0.0942 μs 0.0534 - - 1.45 KB
QueryBuilding Default Filter 4.705 μs 0.0920 μs 0.1290 μs 0.0534 - - 1.53 KB
QueryBuilding Ordering Rule 5.028 μs 0.0734 μs 0.0686 μs 0.0610 - - 1.6 KB