public SqlStatement TranslateSelect(LinqCommand command) { var context = new TranslationContext(_dbModel, command); // convert lambda params into an initial set of ExternalValueExpression objects; foreach (var prm in command.Lambda.Parameters) { var inpParam = new ExternalValueExpression(prm); context.ExternalValues.Add(inpParam); } //Analyze/transform query expression var selectExpr = TranslateSelectExpression(command.Lambda.Body, context); //Build SQL, compile row reader var sqlBuilder = _dbModel.Driver.CreateLinqSqlBuilder(_dbModel, command); var sqlStmt = sqlBuilder.BuildSelectStatement(selectExpr); var rowReader = CompileRowReader(context); var outType = context.CurrentSelect.ReaderOutputType;//.RowReaderLambda.Body.Type; var rowListCreator = GetListCreator(outType); //check if we need to create implicit result set processor var rowListProcessor = selectExpr.RowListProcessor; if (rowListProcessor == null) { var returnsResultSet = typeof(IQueryable).IsAssignableFrom(command.Lambda.Body.Type); if (!returnsResultSet) { rowListProcessor = RowListProcessor.CreateFirstSingleLast("First", outType); } } sqlStmt.ResultProcessor = new DataReaderProcessor() { RowReader = rowReader, RowListCreator = rowListCreator, RowListProcessor = rowListProcessor }; return(sqlStmt); }
protected virtual SelectExpression TranslateSelectExpression(LinqCommand cmd, TranslationContext context) { if (cmd.SelectExpression != null) //special case for Md1, Select is provided in command { context.CurrentSelect = cmd.SelectExpression; return(cmd.SelectExpression); } var linqExpr = cmd.Lambda.Body; var exprChain = ExpressionChain.Build(linqExpr); var tableExpr = _translator.ExtractFirstTable(exprChain[0], context); var selectExpression = _translator.Analyze(exprChain, tableExpr, context); // Check expected type - it will be used for final result conversion if query returns a single value (like Count() query) var resultType = exprChain[exprChain.Count - 1].Type; if (resultType.IsGenericQueryable()) { resultType = selectExpression.Type; } _translator.BuildSelectResultReaderAndCutOutSql(selectExpression, context, resultType); BuildOffsetsAndLimits(context); // then prepare Parts for SQL translation CheckTablesAlias(context); CheckColumnNamesAliases(context); cmd.SelectExpression = context.CurrentSelect; return(context.CurrentSelect); }
// Note: command expected to be analyzed already public SqlStatement Translate(LinqCommand command) { // pre-process; special commands do not produce lambda when command is created - only SqlCacheKey so that SQL // is looked up in cache and we do not need anything else; building actual query lambda is encoded in setup Action, // which we invoke here; // also dynamic linq queries postpone rewrite (changing locals to parameters) until late time switch (command) { case SpecialLinqCommand specCmd: specCmd.SetupAction?.Invoke(specCmd); break; case DynamicLinqCommand dynCmd: if (command.Lambda == null) { LinqCommandRewriter.RewriteToLambda(dynCmd); } break; } //switch try { switch (command.Operation) { case LinqOperation.Select: return(TranslateSelect(command)); case LinqOperation.Update: case LinqOperation.Delete: case LinqOperation.Insert: default: return(TranslateNonQuery((DynamicLinqCommand)command)); } //switch } catch (LinqTranslationException) { throw; // if it is already Linq translation exception, pass it up. } catch (Exception ex) { var message = "Linq to SQL translation failed, invalid expression: " + ex.Message; throw new LinqTranslationException(message, command, ex); } }
public NonQueryLinqCommand(LinqCommand baseLinqCommand, DbTableInfo targetTable, SelectExpression baseSelect) { BaseLinqCommand = baseLinqCommand; BaseSelect = baseSelect; TargetTable = targetTable; }