Skip to content

Commit

Permalink
1. Change the property "Group" of DataSourceResult to "Groups".
Browse files Browse the repository at this point in the history
2. Add new property "Aggregate" to DataSourceRequest.
3. Fixed getting wrong grouping data in the request using aggregates in grouping configuration.
  • Loading branch information
JftCoCo committed Jul 5, 2019
1 parent c9aaee6 commit 48787be
Show file tree
Hide file tree
Showing 12 changed files with 158 additions and 59 deletions.
30 changes: 28 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (console)",
"name": ".NET Core Launch 1.0(console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
Expand All @@ -16,7 +16,33 @@
// For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window
"console": "internalConsole",
"stopAtEntry": false,
"internalConsoleOptions": "openOnSessionStart"
"internalConsoleOptions": "openOnSessionStart",
"logging": {
"engineLogging": false,
"moduleLoad": false,
"exceptions": true,
"browserStdOut": false
}
},
{
"name": ".NET Core Launch 2.0(console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/src/Kendo.DynamicLinqCore.Test/bin/Debug/netcoreapp2.1/Kendo.DynamicLinqCore.Test.dll",
"args": [],
"cwd": "${workspaceFolder}/src/Kendo.DynamicLinqCore.Test",
// For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window
"console": "internalConsole",
"stopAtEntry": false,
"internalConsoleOptions": "openOnSessionStart",
"logging": {
"engineLogging": false,
"moduleLoad": false,
"exceptions": true,
"browserStdOut": false
}
},
{
"name": ".NET Core Attach",
Expand Down
29 changes: 13 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![Downloads](https://img.shields.io/nuget/dt/Kendo.DynamicLinqCore.svg)](https://www.nuget.org/packages/Kendo.DynamicLinqCore)

## Description
Kendo.DynamicLinqCore implements server paging, filtering, sorting and aggregating to Kendo UI via Dynamic Linq for .Net Core App(1.x ~ 2.x).
Kendo.DynamicLinqCore implements server paging, filtering, sorting, grouping and aggregating to Kendo UI via Dynamic Linq for .Net Core App(1.x ~ 2.x).

## Usage
1. Add the Kendo.DynamicLinqCore NuGet package to your project.
Expand All @@ -22,7 +22,7 @@ schema: {
data: "Data",
total: "Total",
aggregates: "Aggregates",
groups: "Group",
groups: "Groups",
errors: "Errors"
}
```
Expand All @@ -37,7 +37,7 @@ dataSource: {
data: "Data",
total: "Total",
aggregates: "Aggregates",
groups: "Group",
groups: "Groups",
errors: "Errors",
...
},
Expand Down Expand Up @@ -72,12 +72,12 @@ dataSource: {
..... Other kendo grid code .....
```
5. Import the Kendo.DynamicLinqCore namespace.
6. Use the `ToDataSourceResult` extension method to apply paging, sorting and filtering
6. Use the `ToDataSourceResult` extension method to apply paging, sorting, filtering, grouping and aggregating.
```c#
using Kendo.DynamicLinqCore

[WebMethod]
public static DataSourceResult Products(int take, int skip, IEnumerable<Sort> sort, Filter filter, IEnumerable<Aggregator> aggregates, IEnumerable<Sort> group)
public static DataSourceResult Products(int take, int skip, IEnumerable<Sort> sort, Filter filter, IEnumerable<Aggregator> aggregates, IEnumerable<Group> groups)
{
using (var northwind = new Northwind())
{
Expand All @@ -91,7 +91,7 @@ public static DataSourceResult Products(int take, int skip, IEnumerable<Sort> so
UnitsInStock = p.UnitsInStock,
Discontinued = p.Discontinued
})
.ToDataSourceResult(take, skip, sort, filter, aggregates, group);
.ToDataSourceResult(take, skip, sort, filter, aggregates, groups);
}
}
```
Expand All @@ -114,7 +114,7 @@ public IActionResult Products([FromBody] DataSourceRequest requestModel)
UnitsInStock = p.UnitsInStock,
Discontinued = p.Discontinued
})
.ToDataSourceResult(requestModel.Take, requestModel.Skip, requestModel.Sort, requestModel.Filter);
.ToDataSourceResult(requestModel.Take, requestModel.Skip, requestModel.Sort, requestModel.Filter, requestModel.Aggregate, requestModel.Group);
}
}
```
Expand Down Expand Up @@ -143,17 +143,14 @@ public class MyContext : DbContext
4. Run "dotnet pack --configuration Release"

## Note
Kendo.DynamicLinqCore is referred to Kendo.DynamicLinq by [kendo-labs](https://github.com/kendo-labs/dlinq-helpers). Related notes can refer it.
Kendo.DynamicLinqCore is referred to Kendo.DynamicLinq by [Ali Sarkis](https://github.com/mshtawythug/dlinq-helpers).

## Examples
The following examples use Kendo.DynamicLinq(Not Kendo.DynamicLinqCore, but similar) and you can consult.
## Kendo UI Documentation
The following links are Kendo UI online docs(related to this package) and you can refer to.

- [ASP.NET MVC](https://github.com/telerik/kendo-examples-asp-net-mvc/tree/master/grid-crud)
- [ASP.NET Web Forms and Page Methods](https://github.com/telerik/kendo-examples-asp-net/tree/master/grid-page-methods-crud)
- [ASP.NET Web Forms and WCF](https://github.com/telerik/kendo-examples-asp-net/tree/master/grid-wcf-crud)
- [ASP.NET Web Forms and Web Services](https://github.com/telerik/kendo-examples-asp-net/tree/master/grid-web-service-crud)
- [ASP.NET Web Forms and Web API](https://github.com/telerik/kendo-examples-asp-net/tree/master/grid-webapi-crud)
- [Kendo UI Grid](https://docs.telerik.com/kendo-ui/api/javascript/ui/grid)
- [Kendo DataSource](https://docs.telerik.com/kendo-ui/api/javascript/data/datasource)

More Kendo UI Grid configuration can refer to [here](https://demos.telerik.com/kendo-ui/)
More Kendo UI configuration can refer to [here](https://demos.telerik.com/kendo-ui/)


Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.0</TargetFramework>
<TargetFrameworks>netcoreapp1.0;netcoreapp2.1</TargetFrameworks>
</PropertyGroup>

<ItemGroup Condition="'$(TargetFramework)'=='netcoreapp1.0'"></ItemGroup>

<ItemGroup Condition="'$(TargetFramework)'=='netcoreapp2.1'"></ItemGroup>

<ItemGroup>
<ProjectReference Include="../Kendo.DynamicLinqCore/Kendo.DynamicLinqCore.csproj" />
</ItemGroup>
Expand Down
37 changes: 25 additions & 12 deletions src/Kendo.DynamicLinqCore.Test/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,57 +12,70 @@ class Program
Identification = Guid.Parse("F057D609-F1F3-4E5C-BC09-0AC0BBE1007D"),
Name = "Monie",
Introduce = "I'm Monie",
Salary = 1000000,
Salary = 1000,
EmployeeNumber = 10,
Birthday = new DateTime(2000,5,5)
},
new Person {
Identification = Guid.Parse("F586A608-4095-4E8E-8F21-AEFC0DFDB61F"),
Name = "CoCo",
Introduce = "I'm CoCo",
Salary = 2500000,
Salary = 2500,
EmployeeNumber = 77,
Birthday = new DateTime(1986,10,10)
},
new Person {
Identification = Guid.Parse("F4FFE20C-4DE5-4DC5-9686-955FB74EE05E"),
Name = "Kirin",
Salary = 3000000,
Salary = 3000,
EmployeeNumber = 66,
Birthday = new DateTime(1984,7,8)
},
new Person {
Identification = Guid.Parse("CCAB16DB-070B-4A93-846A-81AEEFDD42EE"),
Name = "Rock",
Introduce = "",
Salary = 1750000,
Salary = 1750,
EmployeeNumber = 35,
Birthday = new DateTime(1976,11,6)
},
new Person {
Identification = null,
Name = "Pikachu",
Introduce = "Pika~ Pika~",
Salary = 66000,
Salary = 6600,
EmployeeNumber = 18,
Birthday = new DateTime(2005,3,16)
}
};

static void Main(string[] args)
{
{
#if NETCOREAPP1_0 || NETCOREAPP1_1
Console.WriteLine("/---------- Net Core App 1.x ----------/");
#else
Console.WriteLine("/---------- Net Core App 2.x ----------/");
#endif

Console.WriteLine("----------------------------------------");

/* Test 1 */
var result = people.AsQueryable().ToDataSourceResult(1, 2, null, null, new[]
{
new Aggregator
{
Aggregate = "sum",
Field = "Salary"
},
new Aggregator
{
Aggregate = "average",
Field = "Salary"
}
}, null);

Console.WriteLine("/********** Test 1 **********/");
Console.WriteLine(result.Aggregates);
Console.WriteLine("\r\n/********** Test 1 **********/");
Console.WriteLine(result.Aggregates); // { Salary = { sum = 14850, average = 2970 } }


/* Test 2 */
Expand All @@ -79,10 +92,10 @@ static void Main(string[] args)
Logic = "and"
}, null, null);

Console.WriteLine("/********** Test 2 **********/");
Console.WriteLine("\r\n/********** Test 2 **********/");
foreach (var p in result.Data)
{
Console.WriteLine((p as Person).Name);
Console.WriteLine((p as Person).Name); // Kirin, Rock
}


Expand Down Expand Up @@ -115,10 +128,10 @@ static void Main(string[] args)
Logic = "and"
}, null, null);

Console.WriteLine("/********** Test 3 **********/");
Console.WriteLine("\r\n/********** Test 3 **********/");
foreach (var p in result.Data)
{
Console.WriteLine((p as Person).Name);
Console.WriteLine((p as Person).Name); // CoCo, Monie
}

Console.ReadKey();
Expand Down
1 change: 0 additions & 1 deletion src/Kendo.DynamicLinqCore/Aggregator.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
Expand Down
5 changes: 5 additions & 0 deletions src/Kendo.DynamicLinqCore/DataSourceRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,10 @@ public class DataSourceRequest
/// Specifies the requested grouping .
/// </summary>
public IEnumerable<Group> Group { get; set; }

/// <summary>
/// Specifies the requested aggregators.
/// </summary>
public IEnumerable<Aggregator> Aggregate { get; set; }
}
}
10 changes: 5 additions & 5 deletions src/Kendo.DynamicLinqCore/DataSourceResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@ public class DataSourceResult
/// <summary>
/// Represents a single page of processed grouped data.
/// </summary>
public IEnumerable Group { get; set; }
public IEnumerable Groups { get; set; }

/// <summary>
/// The total number of records available.
/// Represents a requested aggregates.
/// </summary>
public int Total { get; set; }
public object Aggregates { get; set; }

/// <summary>
/// Represents a requested aggregates.
/// The total number of records available.
/// </summary>
public object Aggregates { get; set; }
public int Total { get; set; }

/// <summary>
/// Represents error information from server-side.
Expand Down
57 changes: 56 additions & 1 deletion src/Kendo.DynamicLinqCore/EnumerableExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Linq.Expressions;
using System.Reflection;

namespace Kendo.DynamicLinqCore
{
Expand All @@ -14,7 +16,9 @@ public static dynamic GroupByMany<TElement>(this IEnumerable<TElement> elements,
foreach (var selector in groupSelectors)
{
//compile the Dynamic Expression Lambda for each one
//var expression = DynamicExpressionParser.ParseLambda(typeof(TElement), typeof(object), selector.Field);
var expression = DynamicExpressionParser.ParseLambda(false, typeof(TElement), typeof(object), selector.Field);

//add it to the list
selectors.Add(new GroupSelector<TElement>
{
Expand All @@ -41,7 +45,7 @@ public static dynamic GroupByMany<TElement>(this IEnumerable<TElement> elements,
g => new GroupResult
{
Value = g.Key,
Aggregates = selector.Aggregates,
Aggregates = Aggregates(g.AsQueryable(),selector.Aggregates),
HasSubgroups = groupSelectors.Length > 1,
Count = g.Count(),
Items = g.GroupByMany(nextSelectors), //recursivly group the next selectors
Expand All @@ -52,6 +56,57 @@ public static dynamic GroupByMany<TElement>(this IEnumerable<TElement> elements,
//if there are not more group selectors return data
return elements;
}

private static object Aggregates<T>(IQueryable<T> queryable, IEnumerable<Aggregator> aggregates)
{
if (aggregates != null && aggregates.Any())
{
var objProps = new Dictionary<DynamicProperty, object>();
var groups = aggregates.GroupBy(g => g.Field);
Type type = null;

foreach (var group in groups)
{
var fieldProps = new Dictionary<DynamicProperty, object>();
foreach (var aggregate in group)
{
var prop = typeof(T).GetProperty(aggregate.Field);
var param = Expression.Parameter(typeof(T), "s");
var selector = aggregate.Aggregate == "count" && (Nullable.GetUnderlyingType(prop.PropertyType) != null)
? Expression.Lambda(Expression.NotEqual(Expression.MakeMemberAccess(param, prop), Expression.Constant(null, prop.PropertyType)), param)
: Expression.Lambda(Expression.MakeMemberAccess(param, prop), param);
var mi = aggregate.MethodInfo(typeof(T));
if (mi == null) continue;

var val = queryable.Provider.Execute(Expression.Call(null, mi, aggregate.Aggregate == "count" && (Nullable.GetUnderlyingType(prop.PropertyType) == null)
? new[] { queryable.Expression }
: new[] { queryable.Expression, Expression.Quote(selector) }));

fieldProps.Add(new DynamicProperty(aggregate.Aggregate, typeof(object)), val);
}

type = DynamicClassFactory.CreateType(fieldProps.Keys.ToList());
var fieldObj = Activator.CreateInstance(type);
foreach (var p in fieldProps.Keys)
{
type.GetProperty(p.Name).SetValue(fieldObj, fieldProps[p], null);
}
objProps.Add(new DynamicProperty(group.Key, fieldObj.GetType()), fieldObj);
}

type = DynamicClassFactory.CreateType(objProps.Keys.ToList());

var obj = Activator.CreateInstance(type);
foreach (var p in objProps.Keys)
{
type.GetProperty(p.Name).SetValue(obj, objProps[p], null);
}

return obj;
}

return null;
}

public static IEnumerable<T> Append<T>(this IEnumerable<T> source, T item)
{
Expand Down
Loading

0 comments on commit 48787be

Please sign in to comment.