public Expression GetGrouping(GroupByContext context) { if (Configuration.Linq.GuardGrouping && !context._isGroupingGuardDisabled) { if (context.Element.Lambda.Parameters.Count == 1 && context.Element.Body == context.Element.Lambda.Parameters[0]) { var ex = new LinqToDBException( "You should explicitly specify selected fields for server-side GroupBy() call or add AsEnumerable() call before GroupBy() to perform client-side grouping.\n" + "Set Configuration.Linq.GuardGrouping = false to disable this check.\n" + "Additionally this guard exception can be disabled by extension GroupBy(...).DisableGuard().\n" + "NOTE! By disabling this guard you accept additional Database Connection(s) to the server for processing such requests." ) { HelpLink = "https://github.com/linq2db/linq2db/issues/365" }; throw ex; } } var parameters = context.Builder.ParametersContext.CurrentSqlParameters .Select((p, i) => (p, i)) .ToDictionary(_ => _.p.Expression, _ => _.i); var paramArray = Expression.Parameter(typeof(object[]), "ps"); var groupExpression = context._sequenceExpr.Transform( (parameters, paramArray),
public Expression GetGrouping(GroupByContext context) { if (Configuration.Linq.GuardGrouping) { if (context._element.Lambda.Parameters.Count == 1 && context._element.Body == context._element.Lambda.Parameters[0]) { var ex = new LinqToDBException( "You should explicitly specify selected fields for server-side GroupBy() call or add AsEnumerable() call before GroupBy() to perform client-side grouping.\n" + "Set Configuration.Linq.GuardGrouping = false to disable this check." ) { HelpLink = "https://github.com/linq2db/linq2db/issues/365" }; throw ex; } } var parameters = context.Builder.CurrentSqlParameters .Select((p, i) => new { p, i }) .ToDictionary(_ => _.p.Expression, _ => _.i); var paramArray = Expression.Parameter(typeof(object[]), "ps"); var groupExpression = context._sequenceExpr.Transform(e => { int idx; if (parameters.TryGetValue(e, out idx)) { return (Expression.Convert( Expression.ArrayIndex(paramArray, Expression.Constant(idx)), e.Type)); } return(e); }); var keyParam = Expression.Parameter(typeof(TKey), "key"); // ReSharper disable AssignNullToNotNullAttribute var expr = Expression.Call( null, MemberHelper.MethodOf(() => Queryable.Where(null, (Expression <Func <TSource, bool> >)null)), groupExpression, Expression.Lambda <Func <TSource, bool> >( ExpressionBuilder.Equal(context.Builder.MappingSchema, context._key.Lambda.Body, keyParam), new[] { context._key.Lambda.Parameters[0] })); expr = Expression.Call( null, MemberHelper.MethodOf(() => Queryable.Select(null, (Expression <Func <TSource, TElement> >)null)), expr, context._element.Lambda); // ReSharper restore AssignNullToNotNullAttribute var lambda = Expression.Lambda <Func <IDataContext, TKey, object[], IQueryable <TElement> > >( Expression.Convert(expr, typeof(IQueryable <TElement>)), Expression.Parameter(typeof(IDataContext), "ctx"), keyParam, paramArray); var itemReader = CompiledQuery.Compile(lambda); var keyExpr = context._key.BuildExpression(null, 0, false); var dataReaderLocal = context.Builder.DataReaderLocal; if (!Configuration.AvoidSpecificDataProviderAPI && keyExpr.Find(e => e == dataReaderLocal) != null) { keyExpr = Expression.Block( new[] { context.Builder.DataReaderLocal }, new[] { Expression.Assign(dataReaderLocal, Expression.Convert(ExpressionBuilder.DataReaderParam, context.Builder.DataContext.DataReaderType)), keyExpr }); } var keyReader = Expression.Lambda <Func <IQueryRunner, IDataContext, IDataReader, Expression, object[], TKey> >( keyExpr, new [] { ExpressionBuilder.QueryRunnerParam, ExpressionBuilder.DataContextParam, ExpressionBuilder.DataReaderParam, ExpressionBuilder.ExpressionParam, ExpressionBuilder.ParametersParam }); return(Expression.Call( null, MemberHelper.MethodOf(() => GetGrouping(null, null, null, null, null, null, null, null)), new Expression[] { ExpressionBuilder.QueryRunnerParam, ExpressionBuilder.DataContextParam, ExpressionBuilder.DataReaderParam, Expression.Constant(context.Builder.CurrentSqlParameters), ExpressionBuilder.ExpressionParam, ExpressionBuilder.ParametersParam, Expression.Constant(keyReader.Compile()), Expression.Constant(itemReader) })); }
public Expression GetGrouping(GroupByContext context) { if (Configuration.Linq.GuardGrouping && !context._isGroupingGuardDisabled) { if (context.Element.Lambda.Parameters.Count == 1 && context.Element.Body == context.Element.Lambda.Parameters[0]) { var ex = new LinqToDBException( "You should explicitly specify selected fields for server-side GroupBy() call or add AsEnumerable() call before GroupBy() to perform client-side grouping.\n" + "Set Configuration.Linq.GuardGrouping = false to disable this check.\n" + "Additionally this guard exception can be disabled by extension GroupBy(...).DisableGuard().\n" + "NOTE! By disabling this guard you accept additional Database Connection(s) to the server for processing such requests." ) { HelpLink = "https://github.com/linq2db/linq2db/issues/365" }; throw ex; } } var parameters = context.Builder.CurrentSqlParameters .Select((p, i) => new { p, i }) .ToDictionary(_ => _.p.Expression, _ => _.i); var paramArray = Expression.Parameter(typeof(object[]), "ps"); var groupExpression = context._sequenceExpr.Transform(e => { if (parameters.TryGetValue(e, out var idx)) { return (Expression.Convert( Expression.ArrayIndex(paramArray, Expression.Constant(idx)), e.Type)); } return(e); }); var keyParam = Expression.Parameter(typeof(TKey), "key"); // ReSharper disable AssignNullToNotNullAttribute var expr = Expression.Call( null, MemberHelper.MethodOf(() => Queryable.Where(null, (Expression <Func <TSource, bool> >)null !)), groupExpression, Expression.Lambda <Func <TSource, bool> >( ExpressionBuilder.Equal(context.Builder.MappingSchema, context._key.Lambda.Body, keyParam), new[] { context._key.Lambda.Parameters[0] })); expr = Expression.Call( null, MemberHelper.MethodOf(() => Queryable.Select(null, (Expression <Func <TSource, TElement> >)null !)), expr, context.Element.Lambda); // ReSharper restore AssignNullToNotNullAttribute var lambda = Expression.Lambda <Func <IDataContext, TKey, object?[]?, IQueryable <TElement> > >( Expression.Convert(expr, typeof(IQueryable <TElement>)), Expression.Parameter(typeof(IDataContext), "ctx"), keyParam, paramArray); var itemReader = CompiledQuery.Compile(lambda); var keyExpr = context._key.BuildExpression(null, 0, false); var keyReader = Expression.Lambda <Func <IQueryRunner, IDataContext, IDataReader, Expression, object?[]?, TKey> >( keyExpr, new [] { ExpressionBuilder.QueryRunnerParam, ExpressionBuilder.DataContextParam, ExpressionBuilder.DataReaderParam, ExpressionBuilder.ExpressionParam, ExpressionBuilder.ParametersParam }); return(Expression.Call( null, MemberHelper.MethodOf(() => GetGrouping(null !, null !, null !, null !, null !, null !, null !, null !)), new Expression[] { ExpressionBuilder.QueryRunnerParam, ExpressionBuilder.DataContextParam, ExpressionBuilder.DataReaderParam, Expression.Constant(context.Builder.CurrentSqlParameters), ExpressionBuilder.ExpressionParam, ExpressionBuilder.ParametersParam, keyReader, Expression.Constant(itemReader) })); }