Skip to content

Commit

Permalink
Issue 4 (#5)
Browse files Browse the repository at this point in the history
* Update README.md

* Fixing decimal values

* Added nullable on aggregate, double and int

* HACK to fix issue with EF6
  • Loading branch information
geoperez authored Nov 9, 2017
1 parent 61ace38 commit a8b00c4
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 56 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Now you can use Javascript as backend using [Tubular Node.js module](https://git

Please visit the <a href="http://unosquare.github.io/tubular" target="_blank">Tubular GitHub Page</a> to learn how quickly you can start coding. Don't forget to check out the Tubular Generator which quickly turns models into an awesome UIs!

## NuGet Installation [![NuGet version](https://badge.fury.io/nu/tubular.svg)](http://badge.fury.io/nu/tubular)
## NuGet Installation [![NuGet version](https://badge.fury.io/nu/Tubular.ServerSide.svg)](https://badge.fury.io/nu/Tubular.ServerSide)

The same Nuget contains `.NET Framework 4.5.2` and `.NET Standard 2.0` targets.

Expand Down
1 change: 0 additions & 1 deletion src/Unosquare.Tubular.EmbedioSample/PeopleController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,5 @@ protected bool HandleError(HttpListenerContext context, Exception ex, int status
context.Response.StatusCode = statusCode;
return context.JsonResponse(errorResponse);
}

}
}
54 changes: 35 additions & 19 deletions src/Unosquare.Tubular/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -246,31 +246,47 @@ private static Dictionary<string, object> AggregateSubset(GridColumn[] columns,
var aggregateColumns = columns.Where(c => c.Aggregate != AggregationFunction.None).ToArray();
var payload = new Dictionary<string, object>(aggregateColumns.Length);

void Aggregate(GridColumn column, Func<IQueryable<double>, double> doubleF, Func<IQueryable<decimal>, decimal> decimalF, Func<IQueryable<int>, int> intF, Func<IQueryable<string>, string> stringF, Func<IQueryable<DateTime>, DateTime> dateF)
void Aggregate(GridColumn column, Func<IQueryable<double>, double> doubleF,
Func<IQueryable<decimal>, decimal> decimalF, Func<IQueryable<int>, int> intF,
Func<IQueryable<string>, string> stringF, Func<IQueryable<DateTime>, DateTime> dateF)
{
if (subset.ElementType.GetProperty(column.Name).PropertyType == typeof(double))
{
payload.Add(column.Name, doubleF(subset.Select(column.Name).Cast<double>()));
}
else if (subset.ElementType.GetProperty(column.Name).PropertyType == typeof(decimal))
{
payload.Add(column.Name, decimalF(subset.Select(column.Name).Cast<decimal>()));
}
else if (subset.ElementType.GetProperty(column.Name).PropertyType == typeof(int))
{
payload.Add(column.Name, intF(subset.Select(column.Name).Cast<int>()));
}
else if (subset.ElementType.GetProperty(column.Name).PropertyType == typeof(DateTime))
try
{
if (dateF == null) return;
if (subset.ElementType.GetProperty(column.Name).PropertyType == typeof(double))
{
payload.Add(column.Name, doubleF(subset.Select(column.Name).Cast<double>()));
}
else if (subset.ElementType.GetProperty(column.Name).PropertyType == typeof(decimal))
{
payload.Add(column.Name, decimalF(subset.Select(column.Name).Cast<decimal>()));
}
else if (subset.ElementType.GetProperty(column.Name).PropertyType == typeof(int))
{
payload.Add(column.Name, intF(subset.Select(column.Name).Cast<int>()));
}
else if (subset.ElementType.GetProperty(column.Name).PropertyType == typeof(DateTime))
{
if (dateF == null) return;

payload.Add(column.Name, dateF(subset.Select(column.Name).Cast<DateTime>()));
}
else
{
if (stringF == null) return;

payload.Add(column.Name, dateF(subset.Select(column.Name).Cast<DateTime>()));
payload.Add(column.Name, stringF(subset.Select(column.Name).Cast<string>()));
}
}
else
catch (InvalidOperationException ex)
{
if (stringF == null) return;
// EF6 can't materialize a no-nullable value aggregate function returning NULL, so the logic path is return the ONLY value ZERO
if (ex.Source == "EntityFramework")
{
payload.Add(column.Name, 0);
return;
}

payload.Add(column.Name, stringF(subset.Select(column.Name).Cast<string>()));
throw;
}
}

Expand Down
48 changes: 33 additions & 15 deletions test/Unosquare.Tubular.Tests/AggregationTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
{
using NUnit.Framework;
using System.Linq;
using Unosquare.Tubular.ObjectModel;
using Unosquare.Tubular.Tests.Database;
using ObjectModel;
using Database;

[TestFixture]
class AggregationTest
Expand All @@ -16,7 +16,7 @@ public void SumAggregationTest()
{
var data = dataSource.Take(PageSize).ToList();

var request = new GridDataRequest()
var request = new GridDataRequest
{
Take = PageSize,
Skip = 0,
Expand All @@ -29,16 +29,15 @@ public void SumAggregationTest()
Assert.AreEqual(data.Count, response.Payload.Count, "Same length");

Assert.AreEqual(dataSource.Sum(x => x.Number), response.AggregationPayload["Number"],
"Same sum number");

"Same sum number");
}

[Test]
public void AverageAggregationTest()
{
var data = dataSource.Take(PageSize).ToList();

var request = new GridDataRequest()
var request = new GridDataRequest
{
Take = PageSize,
Skip = 0,
Expand All @@ -50,8 +49,8 @@ public void AverageAggregationTest()

Assert.AreEqual(data.Count, response.Payload.Count, "Same length");

Assert.AreEqual(dataSource.Sum(x => x.Number)/dataSource.Count(), response.AggregationPayload["Number"],
"Same average number");
Assert.AreEqual(dataSource.Sum(x => x.Number) / dataSource.Count(), response.AggregationPayload["Number"],
"Same average number");

}

Expand All @@ -60,7 +59,7 @@ public void MaxAggregationTest()
{
var data = dataSource.Take(PageSize).ToList();

var request = new GridDataRequest()
var request = new GridDataRequest
{
Take = PageSize,
Skip = 0,
Expand All @@ -73,15 +72,15 @@ public void MaxAggregationTest()
Assert.AreEqual(data.Count, response.Payload.Count, "Same length");

Assert.AreEqual(dataSource.Max(x => x.Id), response.AggregationPayload["Id"],
"Same max number");
"Same max number");
}

[Test]
public void MinAggregationTest()
{
var data = dataSource.Take(PageSize).ToList();

var request = new GridDataRequest()
var request = new GridDataRequest
{
Take = PageSize,
Skip = 0,
Expand All @@ -94,15 +93,15 @@ public void MinAggregationTest()
Assert.AreEqual(data.Count, response.Payload.Count, "Same length");

Assert.AreEqual(dataSource.Min(x => x.Id), response.AggregationPayload["Id"],
"Same min number");
"Same min number");
}

[Test]
public void CountAggregationTest()
{
var data = dataSource.Take(PageSize).ToList();

var request = new GridDataRequest()
var request = new GridDataRequest
{
Take = PageSize,
Skip = 0,
Expand All @@ -115,7 +114,26 @@ public void CountAggregationTest()
Assert.AreEqual(data.Count, response.Payload.Count, "Same length");

Assert.AreEqual(dataSource.Count(), response.AggregationPayload["Number"],
"Same count number");
"Same count number");
}

[Test]
public void EmptySetSumAggregation_ReturnsSumZero()
{
var request = new GridDataRequest
{
Take = PageSize,
Skip = 0,
Search = new Filter { Text = string.Empty, Operator = CompareOperators.None },
Columns = Thing.GetColumnsWithAggregateDoubleAndInvalidDate(AggregationFunction.Sum),
TimezoneOffset = 360
};

var response = request.CreateGridDataResponse(dataSource);

Assert.AreEqual(0, response.Payload.Count, "Same length");
Assert.IsTrue(response.AggregationPayload.Any());
Assert.AreEqual(0, response.AggregationPayload.First().Value, "Sum zero");
}
}
}
}
63 changes: 44 additions & 19 deletions test/Unosquare.Tubular.Tests/Database/Thing.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
namespace Unosquare.Tubular.Tests.Database
{
using System;
using ObjectModel;

public class Thing
Expand All @@ -16,9 +17,9 @@ public class Thing

public string Color { get; set; }

public System.DateTime Date { get; set; }
public DateTime Date { get; set; }

public System.DateTime? NullableDate { get; set; }
public DateTime? NullableDate { get; set; }

public bool IsShipped { get; set; }

Expand Down Expand Up @@ -77,7 +78,7 @@ public static GridColumn[] GetColumnsWithIdFilter(string filter, CompareOperator
{
Name = "Id",
Filter = new Filter() {Text = filter, Operator = oper},
DataType = Tubular.DataType.Numeric
DataType = DataType.Numeric
},
new GridColumn {Name = "Name"},
new GridColumn {Name = "Date"},
Expand All @@ -96,8 +97,8 @@ public static GridColumn[] GetColumnsWithColorFilter(string filter, CompareOpera
new GridColumn
{
Name = "Color",
Filter = new Filter() { Text = filter, Operator = oper },
DataType = Tubular.DataType.String
Filter = new Filter() {Text = filter, Operator = oper},
DataType = DataType.String
}
};
}
Expand All @@ -110,32 +111,33 @@ public static GridColumn[] GetColumnsWithBetweenFilter(string filter, string[] a
{
Name = "Id",
Filter = new Filter() {Text = filter, Argument = arguments, Operator = CompareOperators.Between},
DataType = Tubular.DataType.Numeric
DataType = DataType.Numeric
},
new GridColumn {Name = "Name"},
new GridColumn {Name = "Date"},
new GridColumn {Name = "IsShipped"}
};
}

public static GridColumn[] GetColumnsWithMultipleFilter(string [] arguments, CompareOperators oper)
public static GridColumn[] GetColumnsWithMultipleFilter(string[] arguments, CompareOperators oper)
{
return new[]
{
new GridColumn {Name = "Id"},
new GridColumn {Name = "Name"},
new GridColumn {Name = "Date"},
new GridColumn {Name = "IsShipped"},
new GridColumn
new GridColumn
{
Name = "Color",
Filter = new Filter() { Argument = arguments, Operator = oper },
DataType = Tubular.DataType.String
Filter = new Filter() {Argument = arguments, Operator = oper},
DataType = DataType.String
}
};
}

public static GridColumn[] GetColumnsWithDateFilter(string filter, CompareOperators oper, Tubular.DataType dataType)
public static GridColumn[] GetColumnsWithDateFilter(string filter, CompareOperators oper,
DataType dataType)
{
return new[]
{
Expand All @@ -145,7 +147,7 @@ public static GridColumn[] GetColumnsWithDateFilter(string filter, CompareOperat
new GridColumn
{
Name = "Date",
Filter = new Filter() {Text = filter, Operator = oper, },
Filter = new Filter() {Text = filter, Operator = oper,},
DataType = dataType
}
};
Expand All @@ -163,7 +165,7 @@ public static GridColumn[] GetColumnsWithNumberFilter(string filter, CompareOper
{
Name = "DecimalNumber",
Filter = new Filter() {Text = filter, Operator = oper},
DataType = Tubular.DataType.Numeric
DataType = DataType.Numeric
}
};
}
Expand All @@ -175,22 +177,23 @@ public static GridColumn[] GetColumnsWithBooleanFilter(string filter, CompareOpe
new GridColumn {Name = "Id"},
new GridColumn {Name = "Name"},
new GridColumn {Name = "Date"},
new GridColumn {
new GridColumn
{
Name = "IsShipped",
Searchable = false,
Filter = new Filter() { Text = filter, Operator = oper, },
DataType = Tubular.DataType.Boolean,
Filter = new Filter() {Text = filter, Operator = oper,},
DataType = DataType.Boolean,
}
};
}

public static GridColumn[] GetColumnsWithAggregateDouble(AggregationFunction aggregation)
public static GridColumn[] GetColumnsWithAggregateDouble(AggregationFunction aggregation)
{
return new[]
{
new GridColumn {Name = "Id"},
new GridColumn {Name = "Number", Aggregate = aggregation},
new GridColumn {Name = "DecimalNumber" },
new GridColumn {Name = "DecimalNumber"},
new GridColumn {Name = "Name"},
new GridColumn {Name = "Date"}
};
Expand All @@ -202,10 +205,32 @@ public static GridColumn[] GetColumnsWithAggregateInt(AggregationFunction aggreg
{
new GridColumn {Name = "Id", Aggregate = aggregation},
new GridColumn {Name = "Number"},
new GridColumn {Name = "DecimalNumber" },
new GridColumn {Name = "DecimalNumber"},
new GridColumn {Name = "Name"},
new GridColumn {Name = "Date"}
};
}

public static GridColumn[] GetColumnsWithAggregateDoubleAndInvalidDate(AggregationFunction aggregation)
{
return new[]
{
new GridColumn {Name = "Id"},
new GridColumn {Name = "Number"},
new GridColumn {Name = "DecimalNumber", Aggregate = aggregation, DataType = DataType.Numeric },
new GridColumn {Name = "Name"},
new GridColumn
{
Name = "Date",
Filter = new Filter
{
Argument = new[] {DateTime.Now.ToShortDateString()},
HasFilter = true,
Text = DateTime.Now.ToShortDateString(),
Operator = CompareOperators.Equals
}
}
};
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netcoreapp2.0;net452</TargetFrameworks>
<TargetFrameworks>net452;netcoreapp2.0</TargetFrameworks>
<AssemblyName>Unosquare.Tubular.Tests</AssemblyName>
<PackageId>Unosquare.Tubular.Tests</PackageId>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
Expand Down

0 comments on commit a8b00c4

Please sign in to comment.