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); }
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