Example #1
0
        /// <summary>
        /// Builds the ExpressionQuery main Expression, given a Table (or projection) expression
        /// </summary>
        /// <param name="expressions"></param>
        /// <param name="tableExpression"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        protected Expression BuildSelectExpression(ExpressionChain expressions, Expression tableExpression, TranslationContext context)
        {
            // Check expected type - it will be used for final result conversion if query returns a single value (like Count() query)
            var resultType = expressions[expressions.Count - 1].Type;

            if (resultType.IsGenericQueryable())
            {
                resultType = null;
            }
            var selectExpression = _translator.Analyze(expressions, tableExpression, context);

            _translator.BuildSelect(selectExpression, context, resultType);
            return(selectExpression);
        }
Example #2
0
        private TranslatedLinqCommand TranslateSelect(LinqCommand command)
        {
            LinqCommandPreprocessor.PreprocessCommand(_dbModel.EntityApp.Model, command);
            var context = new TranslationContext(_dbModel, command);
            var cmdInfo = command.Info;

            // convert lambda params into an initial set of ExternalValueExpression objects;
            foreach (var prm in cmdInfo.Lambda.Parameters)
            {
                var inpParam = new ExternalValueExpression(prm);
                context.ExternalValues.Add(inpParam);
            }
            //Analyze/transform query expression
            var exprChain  = ExpressionChain.Build(cmdInfo.Lambda.Body);
            var selectExpr = BuildSelectExpression(exprChain, context);
            // Analyze external values (parameters?), create DbParameters
            var commandParams = BuildParameters(command, context);
            // If there's at least one parameter that must be converted to literal (ex: value list), we cannot cache the query
            bool canCache = !context.ExternalValues.Any(v => v.SqlUse == ExternalValueSqlUse.Literal);

            if (!canCache)
            {
                command.Info.Flags |= LinqCommandFlags.NoQueryCache;
            }
            //Build SQL, compile object materializer
            var sqlBuilder   = new SqlBuilder(_dbModel);
            var sqlStatement = sqlBuilder.BuildSelect(selectExpr);
            // Parameters are represented as {2}, {3}, etc.
            // Braces in string literals are escaped and are represented as '{0}' and '{1}'
            var sqlTemplate       = sqlStatement.ToString();
            var sql               = FormatSql(sqlTemplate, commandParams);
            var objMaterializer   = CompileObjectMaterializer(context);
            var outType           = context.CurrentSelect.Reader.Body.Type;
            var resultListCreator = ReflectionHelper.GetCompiledGenericListCreator(outType);

            //check if we need to create implicit result set processor
            if (selectExpr.ResultsProcessor == null)
            {
                var returnsResultSet = typeof(IQueryable).IsAssignableFrom(cmdInfo.Lambda.Body.Type);
                if (!returnsResultSet)
                {
                    selectExpr.ResultsProcessor = QueryResultsProcessor.CreateFirstSingleLast("First", outType);
                }
            }
            var sqlQuery = new TranslatedLinqCommand(sqlTemplate, sql, commandParams, command.Info.Flags,
                                                     objMaterializer, selectExpr.ResultsProcessor, resultListCreator);

            return(sqlQuery);
        }
Example #3
0
        public static ExpressionChain Build(Expression expression)
        {
            var exprChain = new ExpressionChain();

            Build(exprChain, expression);
            if (exprChain.Count > 1)
            {
                exprChain.Reverse();
            }
            if (exprChain.Count == 0)
            {
                exprChain.Add(expression);
            }
            return(exprChain);
        }
Example #4
0
        /// <summary>
        /// Builds and chains the provided Expressions
        /// </summary>
        /// <param name="expressionChain"></param>
        /// <param name="context"></param>
        protected virtual SelectExpression BuildSelectExpression(ExpressionChain expressionChain, TranslationContext context)
        {
            var tableExpr = _translator.ExtractFirstTable(expressionChain[0], context);

            BuildSelectExpression(expressionChain, tableExpr, context);
            BuildOffsetsAndLimits(context);
            // then prepare Parts for SQL translation
            CheckTablesAlias(context);
            CheckColumnNamesAliases(context);
            // now, we optimize anything we can
            OptimizeQuery(context);
            context.CurrentSelect.CommandInfo = context.Command.Info; //copy command info to final select
            // in the very end, we keep the SELECT clause
            return(context.CurrentSelect);
        }
Example #5
0
        private static void Build(ExpressionChain chain, Expression expression)
        {
            if (expression.NodeType != ExpressionType.Call)
            {
                return;
            }
            var callExpr = expression as MethodCallExpression;

            if (callExpr.Object != null || callExpr.Method.DeclaringType != typeof(Queryable))
            {
                return;
            }
            chain.Add(callExpr);
            Build(chain, callExpr.Arguments[0]);
        }
Example #6
0
        private TranslatedLinqCommand TranslateNonQuery(LinqCommand command)
        {
            LinqCommandPreprocessor.PreprocessCommand(_dbModel.EntityApp.Model, command);
            var translCtx = new TranslationContext(_dbModel, command);
            var cmdInfo   = command.Info;

            // convert lambda params into an initial set of ExternalValueExpression objects;
            foreach (var prm in cmdInfo.Lambda.Parameters)
            {
                var inpParam = new ExternalValueExpression(prm);
                translCtx.ExternalValues.Add(inpParam);
            }
            //Analyze/transform base select query
            var exprChain  = ExpressionChain.Build(cmdInfo.Lambda.Body);
            var selectExpr = BuildSelectExpression(exprChain, translCtx);
            // Analyze external values (parameters?), create DbParameters
            var cmdParams = BuildParameters(command, translCtx);
            var flags     = command.Info.Flags;
            // If there's at least one parameter that must be converted to literal (ex: value list), we cannot cache the query
            bool canCache = !translCtx.ExternalValues.Any(v => v.SqlUse == ExternalValueSqlUse.Literal);

            if (!canCache)
            {
                flags |= LinqCommandFlags.NoQueryCache;
            }

            // !!! Before that, everyting is the same as in TranslateSelect
            var targetEnt       = command.TargetEntity;
            var targetTable     = _dbModel.GetTable(targetEnt.EntityType);
            var targetTableExpr = new TableExpression(targetTable);
            var commandData     = new NonQueryLinqCommandData(command, selectExpr, targetTableExpr);
            // Analyze base query output expression
            var readerBody = selectExpr.Reader.Body;

            switch (command.CommandType)
            {
            case LinqCommandType.Update:
            case LinqCommandType.Insert:
                Util.Check(readerBody.NodeType == ExpressionType.New, "Query for LINQ {0} command must return New object", commandData.CommandType);
                var newExpr   = readerBody as NewExpression;
                var outValues = selectExpr.Operands.ToList();
                for (int i = 0; i < newExpr.Members.Count; i++)
                {
                    var memberName = newExpr.Members[i].Name;
                    var memberInfo = targetEnt.GetMember(memberName);
                    Util.Check(memberInfo != null, "Member {0} not found in entity {1}.", memberName, targetEnt, targetEnt.EntityType);
                    switch (memberInfo.Kind)
                    {
                    case MemberKind.Column:
                        var col = _translator.CreateColumn(targetTableExpr, memberName, translCtx);
                        commandData.TargetColumns.Add(col);
                        commandData.SelectOutputValues.Add(outValues[i]);
                        break;

                    case MemberKind.EntityRef:
                        var fromKey = memberInfo.ReferenceInfo.FromKey;
                        Util.Check(fromKey.ExpandedKeyMembers.Count == 1,
                                   "References with composite keys are not supported in LINQ non-query operations. Reference: ", memberName);
                        var pkMember = fromKey.ExpandedKeyMembers[0].Member;
                        var col2     = _translator.CreateColumn(targetTableExpr, pkMember.MemberName, translCtx);
                        commandData.TargetColumns.Add(col2);
                        commandData.SelectOutputValues.Add(outValues[i]);
                        break;

                    default:
                        Util.Throw("Property cannot be used in the context: {0}.", memberName);
                        break;
                    }
                }
                break;

            case LinqCommandType.Delete:
                commandData.SelectOutputValues.Add(readerBody); //should return single value - primary key
                break;
            }
            // Build SQL
            var sqlBuilder  = new SqlBuilder(_dbModel);
            var sqlStmt     = sqlBuilder.BuildNonQuery(commandData);
            var sqlTemplate = sqlStmt.ToString();
            var defaultSql  = FormatSql(sqlTemplate, cmdParams);

            return(new TranslatedLinqCommand(sqlTemplate, defaultSql, cmdParams, flags));
        } //method