/// <summary> /// Visits the given node. /// </summary> /// <param name="expression"> The expression to visit. </param> /// <returns> /// An Expression to the translated input expression. /// </returns> public override Expression Visit(Expression expression) { if (_topLevelProjection && (QueryModelVisitor.Expression as MethodCallExpression)?.Method.MethodIsClosedFormOf( QueryModelVisitor.QueryCompilationContext.QueryMethodProvider.GroupByMethod) == true) { var translation = new GroupByAggregateTranslatingExpressionVisitor(this) .Translate(expression); if (translation != null) { QueryModelVisitor.RequiresStreamingGroupResultOperator = false; return(translation); } } _topLevelProjection = false; var selectExpression = QueryModelVisitor.TryGetQuery(_querySource); if (expression != null && !(expression is ConstantExpression) && !(expression is NewExpression) && !(expression is MemberInitExpression) && selectExpression != null) { var existingProjectionsCount = selectExpression.Projection.Count; var sqlExpression = _sqlTranslatingExpressionVisitorFactory .Create(QueryModelVisitor, selectExpression, inProjection: true) .Visit(expression); if (sqlExpression == null) { switch (expression) { case MethodCallExpression methodCallExpression when IncludeCompiler.IsIncludeMethod(methodCallExpression): return(base.Visit(expression)); case QuerySourceReferenceExpression qsre: if (QueryModelVisitor.ParentQueryModelVisitor != null && selectExpression.HandlesQuerySource(qsre.ReferencedQuerySource)) { selectExpression.ProjectStarTable = selectExpression.GetTableForQuerySource(qsre.ReferencedQuerySource); } break; default: QueryModelVisitor.RequiresClientProjection = true; break; } } else { selectExpression.RemoveRangeFromProjection(existingProjectionsCount); if (!(expression is QuerySourceReferenceExpression)) { if (sqlExpression is NullableExpression nullableExpression) { sqlExpression = nullableExpression.Operand; } if (sqlExpression is ColumnExpression) { var index = selectExpression.AddToProjection(sqlExpression); _sourceExpressionProjectionMapping[expression] = selectExpression.Projection[index]; return(expression); } } if (!(sqlExpression is ConstantExpression)) { var targetExpression = QueryModelVisitor.QueryCompilationContext.QuerySourceMapping .GetExpression(_querySource); if (targetExpression.Type == typeof(ValueBuffer)) { var index = selectExpression.AddToProjection(sqlExpression); _sourceExpressionProjectionMapping[expression] = selectExpression.Projection[index]; var readValueExpression = _entityMaterializerSource .CreateReadValueExpression( targetExpression, expression.Type.MakeNullable(), index, sqlExpression.FindProperty(expression.Type)); var outputDataInfo = (expression as SubQueryExpression)?.QueryModel .GetOutputDataInfo(); if (outputDataInfo is StreamedScalarValueInfo) { // Compensate for possible nulls readValueExpression = Expression.Coalesce( readValueExpression, Expression.Default(expression.Type)); } return(Expression.Convert(readValueExpression, expression.Type)); } return(expression); } } } return(base.Visit(expression)); }
/// <summary> /// Visits the given node. /// </summary> /// <param name="expression"> The expression to visit. </param> /// <returns> /// An Expression to the translated input expression. /// </returns> public override Expression Visit(Expression expression) { if (_topLevelProjection && (QueryModelVisitor.Expression as MethodCallExpression)?.Method.MethodIsClosedFormOf( QueryModelVisitor.QueryCompilationContext.QueryMethodProvider.GroupByMethod) == true) { var translation = new GroupByAggregateTranslatingExpressionVisitor(this) .Translate(expression); if (translation != null) { QueryModelVisitor.RequiresStreamingGroupResultOperator = false; return(translation); } } _topLevelProjection = false; if (expression == null || _selectExpression == null) { return(expression); } switch (expression) { case ConstantExpression constantExpression: return(constantExpression); // To save mappings so that we can compose afterwards case NewExpression newExpression: return(VisitNew(newExpression)); case MemberInitExpression memberInitExpression: return(VisitMemberInit(memberInitExpression)); case QuerySourceReferenceExpression qsre: if (_selectExpression.HandlesQuerySource(qsre.ReferencedQuerySource)) { _selectExpression.ProjectStarTable = _selectExpression.GetTableForQuerySource(qsre.ReferencedQuerySource); } return(qsre); // Skip over Include method case MethodCallExpression methodCallExpression when IncludeCompiler.IsIncludeMethod(methodCallExpression): return(methodCallExpression); default: var sqlExpression = _sqlTranslatingExpressionVisitorFactory .Create(QueryModelVisitor, _selectExpression, inProjection: true) .Visit(expression); if (sqlExpression == null) { QueryModelVisitor.RequiresClientProjection = true; return(base.Visit(expression)); } else if (sqlExpression is ConstantExpression) { return(base.Visit(expression)); } else { if (sqlExpression is NullableExpression nullableExpression) { sqlExpression = nullableExpression.Operand; } if (sqlExpression is ColumnExpression) { var index = _selectExpression.AddToProjection(sqlExpression); _sourceExpressionProjectionMapping[expression] = _selectExpression.Projection[index]; return(expression); } var targetExpression = QueryModelVisitor.QueryCompilationContext.QuerySourceMapping .GetExpression(_querySource); if (targetExpression.Type == typeof(ValueBuffer)) { var index = _selectExpression.AddToProjection(sqlExpression); _sourceExpressionProjectionMapping[expression] = _selectExpression.Projection[index]; var readValueExpression = _entityMaterializerSource .CreateReadValueExpression( targetExpression, expression.Type.MakeNullable(), index, sqlExpression.FindProperty(expression.Type)); var outputDataInfo = (expression as SubQueryExpression)?.QueryModel .GetOutputDataInfo(); if (outputDataInfo is StreamedScalarValueInfo) { // Compensate for possible nulls readValueExpression = Expression.Coalesce( readValueExpression, Expression.Default(expression.Type)); } return(Expression.Convert(readValueExpression, expression.Type)); } return(expression); } } }