Beispiel #1
0
        protected override Expression VisitProjection(SqlProjectionExpression projectionExpression)
        {
            if (typeof(RelatedDataAccessObjects <>).IsAssignableFromIgnoreGenericParameters(projectionExpression.Type))
            {
                var elementType = projectionExpression.Type.GetGenericArguments()[0];
                var originalPlaceholderCount = 0;
                var currentPlaceholderCount  = originalPlaceholderCount;

                var replacedExpressions = new List <Expression>();
                projectionExpression = (SqlProjectionExpression)SqlOuterQueryReferencePlaceholderSubstitutor.Substitute(projectionExpression, ref currentPlaceholderCount, replacedExpressions);
                var values = replacedExpressions.Select(c => Expression.Convert(this.Visit(c), typeof(object))).ToList();
                var where = projectionExpression.Select.Where;

                var typeDescriptor = this.dataAccessModel.TypeDescriptorProvider.GetTypeDescriptor(elementType);
                var columns        = QueryBinder.GetColumnInfos(this.dataAccessModel.TypeDescriptorProvider, typeDescriptor.PersistedProperties);

                var columnExpression = (SqlColumnExpression)SqlExpressionFinder.FindFirst(where, c => c.NodeType == (ExpressionType)SqlExpressionType.Column);
                var match            = columns.Single(d => d.ColumnName == columnExpression.Name);

                var reference = Expression.Call(Expression.Constant(this.dataAccessModel), MethodInfoFastRef.DataAccessModelGetReferenceByValuesMethod.MakeGenericMethod(match.ForeignType.Type), Expression.NewArrayInit(typeof(object), values));
                var property  = typeDescriptor.GetRelationshipInfos().Single(c => c.ReferencingProperty == match.RootProperty).TargetProperty;

                return(Expression.Convert(Expression.Property(reference, property), this.dataAccessModel.GetConcreteTypeFromDefinitionType(property.PropertyType)));
            }
            else
            {
                var currentPlaceholderCount = 0;
                var replacedExpressions     = new List <Expression>();
                projectionExpression = (SqlProjectionExpression)SqlOuterQueryReferencePlaceholderSubstitutor.Substitute(projectionExpression, ref currentPlaceholderCount, replacedExpressions);

                var newColumnIndexes = projectionExpression.Select.Columns.Select((c, i) => new { c.Name, i }).ToDictionary(d => d.Name, d => d.i);

                var savedScope = this.scope;
                this.scope = new ProjectionBuilderScope(newColumnIndexes);
                var projectionProjector = Expression.Lambda(this.Visit(projectionExpression.Projector), objectProjector, dataReader, versionParameter, dynamicParameters);
                this.scope = savedScope;

                var values = replacedExpressions.Select(c => (Expression)Expression.Convert(Visit(c), typeof(object))).ToList();

                var method = TypeUtils.GetMethod <SqlQueryProvider>(c => c.BuildExecution(default(SqlProjectionExpression), default(LambdaExpression), default(object[])));

                MethodInfo evaluate;

                if (projectionExpression.Type.GetSequenceElementType() == null)
                {
                    evaluate = MethodInfoFastRef.ExecutionBuildResultEvaluateMethod.MakeGenericMethod(projectionExpression.Type);
                }
                else
                {
                    evaluate = MethodInfoFastRef.ExecutionBuildResultEvaluateMethod.MakeGenericMethod(typeof(IEnumerable <>).MakeGenericType(projectionExpression.Type.GetSequenceElementType()));
                }

                return(Expression.Call(Expression.Call(Expression.Property(this.objectProjector, "QueryProvider"), method, Expression.Constant(projectionExpression), projectionProjector, Expression.NewArrayInit(typeof(object), values)), evaluate));
            }
        }
        internal static IEnumerable <Expression> GetIncludeJoins(this Expression expression)
        {
            var select = expression as SqlSelectExpression;

            if (select != null)
            {
                yield break;
            }

            var join = expression as SqlJoinExpression;

            if (join?.JoinType != SqlJoinType.Left)
            {
                yield break;
            }

            foreach (var value in join.Left.GetIncludeJoins())
            {
                if (value == null)
                {
                    if (!SqlExpressionFinder.FindExists(join.JoinCondition, c => !expressionTypes.Contains(c.NodeType)))
                    {
                        if (SqlExpressionFinder.FindExists(join.JoinCondition, c => c.NodeType == ExpressionType.Equal))
                        {
                            yield return(join.JoinCondition);
                        }
                    }
                }
                else
                {
                    yield return(value);
                }
            }

            foreach (var value in join.Right.GetIncludeJoins())
            {
                if (value == null)
                {
                    if (!SqlExpressionFinder.FindExists(join.JoinCondition, c => !expressionTypes.Contains(c.NodeType)))
                    {
                        if (SqlExpressionFinder.FindExists(join.JoinCondition, c => c.NodeType == ExpressionType.Equal))
                        {
                            yield return(join.JoinCondition);
                        }
                    }
                }
                else
                {
                    yield return(value);
                }
            }
        }