From ba702d3e815bd6df8bfc94350384e23ab8b2b8c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Leb=C3=A9e?= Date: Tue, 13 Mar 2018 22:16:58 -0500 Subject: [PATCH] Aggregates are advancing well. --- PoweredSoft.DynamicLinq.Test/GroupingTests.cs | 27 ++++------ .../Helpers/QueryableHelpers.cs | 54 +++++++++++++------ 2 files changed, 46 insertions(+), 35 deletions(-) diff --git a/PoweredSoft.DynamicLinq.Test/GroupingTests.cs b/PoweredSoft.DynamicLinq.Test/GroupingTests.cs index bc9f24e..04fa6c8 100644 --- a/PoweredSoft.DynamicLinq.Test/GroupingTests.cs +++ b/PoweredSoft.DynamicLinq.Test/GroupingTests.cs @@ -83,37 +83,28 @@ namespace PoweredSoft.DynamicLinq.Test Count = t.Count(), });*/ - BlogContext bc = null; - if (bc != null) + TestData.Sales.GroupBy(t => new { t.ClientId }).Select(t => new { - bc.Authors.GroupBy(t => new { t.LastName }).Select(t => new - { - t.Key.LastName, - Count = t.Count() - - }); - } + TheClientId = t.Key.ClientId, + Count = t.Count(), + LongCount = t.LongCount(), + TaxAverage = t.Average(t2 => t2.Tax) + }); var dynamicSyntax2 = TestData.Sales .AsQueryable() .GroupBy(t => t.Path("ClientId")) .Select(t => { - t.Key("TheClientId", "ClientId"); - t.Count("Count"); - /* + t.Key("TheClientId", "ClientId"); + t.Count("Count"); t.LongCount("LongCount"); t.Sum("NetSales"); t.Average("Tax", "TaxAverage"); - t.ToList("Sales");*/ + //t.ToList("Sales"); }); var result = dynamicSyntax2.ToObjectList(); } - - private object compare(MockSale arg) - { - throw new NotImplementedException(); - } } } diff --git a/PoweredSoft.DynamicLinq/Helpers/QueryableHelpers.cs b/PoweredSoft.DynamicLinq/Helpers/QueryableHelpers.cs index 426ba2d..e63ce35 100644 --- a/PoweredSoft.DynamicLinq/Helpers/QueryableHelpers.cs +++ b/PoweredSoft.DynamicLinq/Helpers/QueryableHelpers.cs @@ -139,26 +139,12 @@ namespace PoweredSoft.DynamicLinq.Helpers var mi = Expression.MemberInit(ctor, bindings); var lambda = Expression.Lambda(mi, parameter); - /* - public static IQueryable Tester(IQueryable data) - { - var source = Expression.Parameter(typeof(TypeOne), "source"); - var selector = Expression.Lambda>( - Expression.MemberInit(Expression.New(typeof(TypeTwo)), - Expression.Bind(typeof(TypeTwo).GetProperty("TwoProp"), Expression.Property(source, "OneProp"))), - source); - return data.Select(selector); - }*/ - - //public static IQueryable Select(this IQueryable source, Expression> selector); - - var selectExpr = Expression.Call(typeof(Queryable), "Select", new[] { query.ElementType, typeToCreate }, query.Expression, lambda); var result = query.Provider.CreateQuery(selectExpr); return result; } - private static Expression CreateSelectExpression(IQueryable query, ParameterExpression parameter, SelectTypes selectType, string path) + private static Expression CreateSelectExpressionForGrouping(IQueryable query, ParameterExpression parameter, SelectTypes selectType, string path) { if (selectType == SelectTypes.Key) { @@ -166,22 +152,56 @@ namespace PoweredSoft.DynamicLinq.Helpers } else if (selectType == SelectTypes.Count) { - // TODO: check if we need to ensure if grouped before getting second generic argument. var notGroupedType = parameter.Type.GenericTypeArguments[1]; var body = Expression.Call(typeof(Enumerable), "Count", new[] { notGroupedType }, parameter); return body; } else if (selectType == SelectTypes.LongCount) { - // TODO: check if we need to ensure if grouped before getting second generic argument. var notGroupedType = parameter.Type.GenericTypeArguments[1]; var body = Expression.Call(typeof(Enumerable), "LongCount", new[] { notGroupedType }, parameter); return body; } + else if (selectType == SelectTypes.Average) + { + /// https://stackoverflow.com/questions/25482097/call-enumerable-average-via-expression + var notGroupedType = parameter.Type.GenericTypeArguments[1]; + var innerParameter = Expression.Parameter(notGroupedType); + var innerMemberExpression = ResolvePathForExpression(innerParameter, path); + var innerMemberLambda = Expression.Lambda(innerMemberExpression, innerParameter); + var body = Expression.Call(typeof(Enumerable), "Average", new[] { notGroupedType }, parameter, innerMemberLambda); + return body; + } + else if (selectType == SelectTypes.Sum) + { + var notGroupedType = parameter.Type.GenericTypeArguments[1]; + var innerParameter = Expression.Parameter(notGroupedType); + var innerMemberExpression = ResolvePathForExpression(innerParameter, path); + var innerMemberLambda = Expression.Lambda(innerMemberExpression, innerParameter); + var body = Expression.Call(typeof(Enumerable), "Sum", new[] { notGroupedType }, parameter, innerMemberLambda); + return body; + } throw new NotSupportedException($"unkown select type {selectType}"); } + private static Expression CreateSelectExpression(IQueryable query, ParameterExpression parameter, SelectTypes selectType, string path) + { + if (!IsGrouping(query)) + throw new NotSupportedException("Select without grouping is not supported yet."); + + return CreateSelectExpressionForGrouping(query, parameter, selectType, path); + } + + private static bool IsGrouping(IQueryable query) + { + // TODO needs to be alot better than this, but it will do for now. + if (query.ElementType.Name.Contains("IGrouping")) + return true; + + return false; + } + public static IQueryable GroupBy(IQueryable query, Type type, string path) { var parameter = Expression.Parameter(type, "t");