예제 #1
0
                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),
예제 #2
0
                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)
                    }));
                }
예제 #3
0
                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)
                    }));
                }