Пример #1
0
        public IEnumerable <T> ExecuteCollection <T>(QueryModel queryModel)
        {
            // Create an expression that returns the current item when invoked
            Expression currentItemExpression = Expression.Property(Expression.Constant(this), "Current");

            // Now replace references like the "i" in "select i" that refers to the "i" in "from i in items"
            var mapping = new QuerySourceMapping();

            mapping.AddMapping(queryModel.MainFromClause, currentItemExpression);
            queryModel.TransformExpressions(e =>
                                            ReferenceReplacingExpressionVisitor.ReplaceClauseReferences(e, mapping, true));

            // Create a lambda that takes our SampleDataSourceItem and passes it through the select clause
            // to produce a type of T. (T may be SampleDataSourceItem, in which case this is an identity function).
            var currentItemProperty = Expression.Parameter(typeof(SampleDataSourceItem));
            var projection          =
                Expression.Lambda <Func <SampleDataSourceItem, T> >(queryModel.SelectClause.Selector, currentItemProperty);
            var projector = projection.Compile();

            for (var i = 0; i < 10; i++)
            {
                Current = new SampleDataSourceItem
                {
                    Name        = "Name " + i,
                    Description = "This describes the item in position " + i
                };

                yield return(projector(Current));
            }
        }
Пример #2
0
        private void UpdateQuerySourceMapping(
            QueryModel queryModel,
            IQuerySource oldQuerySource,
            Expression newExpression)
        {
            var querySourceMapping = new QuerySourceMapping();

            querySourceMapping.AddMapping(oldQuerySource, newExpression);

            queryModel.TransformExpressions(
                e =>
                ReferenceReplacingExpressionVisitor
                .ReplaceClauseReferences(e, querySourceMapping, throwOnUnmappedReferences: false));

            if (newExpression is QuerySourceReferenceExpression qsre)
            {
                var newQuerySource = qsre.ReferencedQuerySource;
                foreach (var queryAnnotation in _queryCompilationContext.QueryAnnotations.Where(qa => qa.QuerySource == oldQuerySource))
                {
                    queryAnnotation.QuerySource = newQuerySource;
                    queryAnnotation.QueryModel  = queryModel;

                    if (queryAnnotation is IncludeResultOperator includeAnnotation &&
                        includeAnnotation.PathFromQuerySource != null)
                    {
                        includeAnnotation.PathFromQuerySource
                            = ReferenceReplacingExpressionVisitor
                              .ReplaceClauseReferences(includeAnnotation.PathFromQuerySource, querySourceMapping, throwOnUnmappedReferences: false);
                    }
                }
            }
        }
Пример #3
0
        public void Replaces_NestedExpressions()
        {
            var expression = Expression.Negate(new QuerySourceReferenceExpression(_oldFromClause));
            var result     = (UnaryExpression)ReferenceReplacingExpressionVisitor.ReplaceClauseReferences(expression, _querySourceMapping, true);

            Assert.That(((QuerySourceReferenceExpression)result.Operand).ReferencedQuerySource, Is.SameAs(_newFromClause));
        }
Пример #4
0
        public void VisitSubQuery_ExpressionUnchanged()
        {
            var expression = new SubQueryExpression(ExpressionHelper.CreateQueryModel <Cook> ());
            var result     = ReferenceReplacingExpressionVisitor.ReplaceClauseReferences(expression, _querySourceMapping, false);

            Assert.That(((SubQueryExpression)result).QueryModel, Is.SameAs(expression.QueryModel));
        }
Пример #5
0
        public void Replaces_QuerySourceReferenceExpressions()
        {
            var expression = new QuerySourceReferenceExpression(_oldFromClause);
            var result     = ReferenceReplacingExpressionVisitor.ReplaceClauseReferences(expression, _querySourceMapping, true);

            Assert.That(((QuerySourceReferenceExpression)result).ReferencedQuerySource, Is.SameAs(_newFromClause));
        }
Пример #6
0
        private void UpdateQuerySourceMapping(
            QueryModel queryModel,
            IQuerySource oldQuerySource,
            Expression newExpression)
        {
            var querySourceMapping = new QuerySourceMapping();

            querySourceMapping.AddMapping(oldQuerySource, newExpression);

            queryModel.TransformExpressions(e =>
                                            ReferenceReplacingExpressionVisitor
                                            .ReplaceClauseReferences(e, querySourceMapping, throwOnUnmappedReferences: false));

            var qsre = newExpression as QuerySourceReferenceExpression;

            if (qsre != null)
            {
                var newQuerySource = qsre.ReferencedQuerySource;
                foreach (var queryAnnotation in _queryAnnotations.Where(qa => qa.QuerySource == oldQuerySource))
                {
                    queryAnnotation.QuerySource = newQuerySource;
                    queryAnnotation.QueryModel  = queryModel;
                }
            }
        }
Пример #7
0
        public void VisitUnknownNonExtensionExpression_Ignored()
        {
            var expression = new UnknownExpression(typeof(object));
            var result     = ReferenceReplacingExpressionVisitor.ReplaceClauseReferences(expression, _querySourceMapping, true);

            Assert.That(result, Is.SameAs(expression));
        }
Пример #8
0
        public void VisitUnmappedReference_IgnoreTrue_Ignored()
        {
            var expression = new QuerySourceReferenceExpression(ExpressionHelper.CreateMainFromClause_Int());
            var result     = ReferenceReplacingExpressionVisitor.ReplaceClauseReferences(expression, _querySourceMapping, false);

            Assert.That(result, Is.SameAs(expression));
        }
Пример #9
0
        protected virtual void FlattenSubQuery(SubQueryExpression subQueryExpression, IFromClause fromClause,
                                               QueryModel queryModel, int destinationIndex)
        {
            ArgumentUtility.CheckNotNull("subQueryExpression", subQueryExpression);
            ArgumentUtility.CheckNotNull("fromClause", fromClause);
            ArgumentUtility.CheckNotNull("queryModel", queryModel);

            CheckFlattenable(subQueryExpression.QueryModel);

            var innerMainFromClause = subQueryExpression.QueryModel.MainFromClause;

            fromClause.CopyFromSource(innerMainFromClause);

            var innerSelectorMapping = new QuerySourceMapping();

            innerSelectorMapping.AddMapping(fromClause, subQueryExpression.QueryModel.SelectClause.Selector);
            queryModel.TransformExpressions(ex =>
                                            ReferenceReplacingExpressionVisitor.ReplaceClauseReferences(ex, innerSelectorMapping, false));

            InsertBodyClauses(subQueryExpression.QueryModel.BodyClauses, queryModel, destinationIndex);

            var innerBodyClauseMapping = new QuerySourceMapping();

            innerBodyClauseMapping.AddMapping(innerMainFromClause, new QuerySourceReferenceExpression(fromClause));
            queryModel.TransformExpressions(ex =>
                                            ReferenceReplacingExpressionVisitor.ReplaceClauseReferences(ex, innerBodyClauseMapping, false));
        }
Пример #10
0
        public void VisitSubQuery_PassesFlagToInner_Throw()
        {
            var expression = new SubQueryExpression(ExpressionHelper.CreateQueryModel <Cook> ());

            expression.QueryModel.SelectClause.Selector = new QuerySourceReferenceExpression(expression.QueryModel.MainFromClause);
            ReferenceReplacingExpressionVisitor.ReplaceClauseReferences(expression, _querySourceMapping, true);
        }
Пример #11
0
        public void VisitExtensionExpression_ChildrenAreProcessed()
        {
            var extensionExpression = new ReducibleExtensionExpression(new QuerySourceReferenceExpression(_oldFromClause));

            var result = (ReducibleExtensionExpression)ReferenceReplacingExpressionVisitor.ReplaceClauseReferences(extensionExpression, _querySourceMapping, true);

            var expectedExpression = new ReducibleExtensionExpression(new QuerySourceReferenceExpression(_newFromClause));

            ExpressionTreeComparer.CheckAreEqualTrees(expectedExpression, result);
        }
Пример #12
0
        private static ClientSideSelect CreateClientSideSelect(Expression expression, QueryModel queryModel)
        {
            // TODO - don't like calling GetGenericArguments here...

            var parameter = Expression.Parameter(expression.Type.GetGenericArguments()[0], "inputParameter");

            var mapping = new QuerySourceMapping();

            mapping.AddMapping(queryModel.MainFromClause, parameter);

            var body = ReferenceReplacingExpressionVisitor.ReplaceClauseReferences(queryModel.SelectClause.Selector, mapping, false);

            var lambda = Expression.Lambda(body, parameter);

            return(new ClientSideSelect(lambda));
        }
Пример #13
0
        public void Replaces_SubQueryExpressions_WithCorrectCloneContext()
        {
            var subQueryModel    = ExpressionHelper.CreateQueryModel <Cook> ();
            var referencedClause = ExpressionHelper.CreateMainFromClause_Int();

            subQueryModel.SelectClause.Selector = new QuerySourceReferenceExpression(referencedClause);
            var expression = new SubQueryExpression(subQueryModel);

            var newReferenceExpression = new QuerySourceReferenceExpression(ExpressionHelper.CreateMainFromClause_Int());

            _querySourceMapping.AddMapping(referencedClause, newReferenceExpression);

            var result = ReferenceReplacingExpressionVisitor.ReplaceClauseReferences(expression, _querySourceMapping, false);
            var newSubQuerySelectClause = ((SubQueryExpression)result).QueryModel.SelectClause;

            Assert.That(newSubQuerySelectClause.Selector, Is.SameAs(newReferenceExpression));
        }
Пример #14
0
        public override void VisitAdditionalFromClause(AdditionalFromClause fromClause, QueryModel queryModel, int index)
        {
            var subQuery = fromClause.FromExpression as SubQueryExpression;

            if (subQuery == null)
            {
                return;
            }

            var subQueryModel = subQuery.QueryModel;

            if (!IsLeftJoin(subQueryModel))
            {
                return;
            }

            var mainFromClause = subQueryModel.MainFromClause;

            var restrictions = subQueryModel.BodyClauses
                               .OfType <WhereClause>()
                               .Select(w => new NhWithClause(w.Predicate));

            var join = new NhJoinClause(mainFromClause.ItemName,
                                        mainFromClause.ItemType,
                                        mainFromClause.FromExpression,
                                        restrictions);

            var innerSelectorMapping = new QuerySourceMapping();

            innerSelectorMapping.AddMapping(fromClause, subQueryModel.SelectClause.Selector);

            queryModel.TransformExpressions(ex => ReferenceReplacingExpressionVisitor.ReplaceClauseReferences(ex, innerSelectorMapping, false));

            queryModel.BodyClauses.RemoveAt(index);
            queryModel.BodyClauses.Insert(index, @join);
            InsertBodyClauses(subQueryModel.BodyClauses.Where(b => !(b is WhereClause)), queryModel, index + 1);

            var innerBodyClauseMapping = new QuerySourceMapping();

            innerBodyClauseMapping.AddMapping(mainFromClause, new QuerySourceReferenceExpression(@join));

            queryModel.TransformExpressions(ex => ReferenceReplacingExpressionVisitor.ReplaceClauseReferences(ex, innerBodyClauseMapping, false));
        }
Пример #15
0
        private void UpdateQueryAnnotations(QueryModel queryModel, QuerySourceMapping querySourceMapping)
        {
            foreach (var queryAnnotation in _queryCompilationContext.QueryAnnotations)
            {
                if (querySourceMapping.ContainsMapping(queryAnnotation.QuerySource))
                {
                    queryAnnotation.QuerySource = querySourceMapping.GetExpression(queryAnnotation.QuerySource)
                                                  .TryGetReferencedQuerySource();
                    queryAnnotation.QueryModel = queryModel;

                    if (queryAnnotation is IncludeResultOperator includeAnnotation &&
                        includeAnnotation.PathFromQuerySource != null)
                    {
                        includeAnnotation.PathFromQuerySource
                            = ReferenceReplacingExpressionVisitor
                              .ReplaceClauseReferences(includeAnnotation.PathFromQuerySource, querySourceMapping, throwOnUnmappedReferences: false);
                    }
                }
            }
        }
        private void ShiftBodyClauses(QueryModel oldQueryModel, QueryModel newQueryModel)
        {
            var querySourceMapping = new QuerySourceMapping();

            querySourceMapping.AddMapping(
                oldQueryModel.MainFromClause,
                new QuerySourceReferenceExpression(newQueryModel.MainFromClause));

            foreach (var bodyClause in oldQueryModel.BodyClauses.ToArray())
            {
                bodyClause.TransformExpressions(expression =>
                                                ReferenceReplacingExpressionVisitor.ReplaceClauseReferences(
                                                    expression,
                                                    querySourceMapping,
                                                    throwOnUnmappedReferences: false));

                oldQueryModel.BodyClauses.Remove(bodyClause);
                newQueryModel.BodyClauses.Add(bodyClause);
            }
        }
Пример #17
0
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        public override void VisitGroupJoinClause(GroupJoinClause groupJoinClause, QueryModel queryModel, int index)
        {
            base.VisitGroupJoinClause(groupJoinClause, queryModel, index);

            // Attempts to rewrite GroupJoin/SelectMany to regular join

            var additionalFromClause
                = queryModel.BodyClauses.ElementAtOrDefault(index + 1)
                  as AdditionalFromClause;

            var querySourceReferenceExpression
                = additionalFromClause?.FromExpression as QuerySourceReferenceExpression;

            if (querySourceReferenceExpression != null &&
                querySourceReferenceExpression.ReferencedQuerySource == groupJoinClause)
            {
                if (queryModel.CountQuerySourceReferences(groupJoinClause) == 1)
                {
                    // GroupJoin/SelectMany can be rewritten to regular Join.

                    queryModel.BodyClauses.RemoveAt(index + 1);
                    queryModel.BodyClauses.RemoveAt(index);
                    queryModel.BodyClauses.Insert(index, groupJoinClause.JoinClause);

                    var querySourceMapping = new QuerySourceMapping();

                    querySourceMapping.AddMapping(
                        additionalFromClause,
                        new QuerySourceReferenceExpression(groupJoinClause.JoinClause));

                    queryModel.TransformExpressions(e =>
                                                    ReferenceReplacingExpressionVisitor.ReplaceClauseReferences(
                                                        e,
                                                        querySourceMapping,
                                                        throwOnUnmappedReferences: false));
                }
            }
        }
Пример #18
0
        private static void FlattenSubQuery(SubQueryExpression subQueryExpression, FromClauseBase fromClause, QueryModel queryModel, int destinationIndex)
        {
            if (!CheckFlattenable(subQueryExpression.QueryModel))
            {
                return;
            }

            var mainFromClause = subQueryExpression.QueryModel.MainFromClause;

            CopyFromClauseData(mainFromClause, fromClause);

            var innerSelectorMapping = new QuerySourceMapping();

            innerSelectorMapping.AddMapping(fromClause, subQueryExpression.QueryModel.SelectClause.Selector);
            queryModel.TransformExpressions(ex => ReferenceReplacingExpressionVisitor.ReplaceClauseReferences(ex, innerSelectorMapping, false));

            InsertBodyClauses(subQueryExpression.QueryModel.BodyClauses, queryModel, destinationIndex);
            InsertResultOperators(subQueryExpression.QueryModel.ResultOperators, queryModel);

            var innerBodyClauseMapping = new QuerySourceMapping();

            innerBodyClauseMapping.AddMapping(mainFromClause, new QuerySourceReferenceExpression(fromClause));
            queryModel.TransformExpressions(ex => ReferenceReplacingExpressionVisitor.ReplaceClauseReferences(ex, innerBodyClauseMapping, false));
        }
Пример #19
0
        public void VisitUnmappedReference_IgnoreFalse_Throws()
        {
            var expression = new QuerySourceReferenceExpression(ExpressionHelper.CreateMainFromClause_Int());

            ReferenceReplacingExpressionVisitor.ReplaceClauseReferences(expression, _querySourceMapping, true);
        }
Пример #20
0
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        protected override void FlattenSubQuery(
            [NotNull] SubQueryExpression subQueryExpression,
            [NotNull] IFromClause fromClause,
            [NotNull] QueryModel queryModel,
            int destinationIndex)
        {
            var subQueryModel = subQueryExpression.QueryModel;

            VisitQueryModel(subQueryModel);

            if ((subQueryModel.ResultOperators
                 .All(ro => ro is CastResultOperator) &&
                 !subQueryModel.BodyClauses.Any(bc => bc is OrderByClause)) ||
                (queryModel.IsIdentityQuery() &&
                 !queryModel.ResultOperators.Any()))
            {
                string itemName;

                var innerMainFromClause  = subQueryExpression.QueryModel.MainFromClause;
                var isGeneratedNameOuter = fromClause.HasGeneratedItemName();

                if (innerMainFromClause.HasGeneratedItemName() &&
                    !isGeneratedNameOuter)
                {
                    itemName = fromClause.ItemName;
                }
                else
                {
                    itemName = innerMainFromClause.ItemName;
                }

                var fromClauseData
                    = new FromClauseData(
                          itemName, innerMainFromClause.ItemType, innerMainFromClause.FromExpression);

                fromClause.CopyFromSource(fromClauseData);

                var innerSelectorMapping = new QuerySourceMapping();

                innerSelectorMapping.AddMapping(fromClause, subQueryExpression.QueryModel.SelectClause.Selector);

                queryModel.TransformExpressions(
                    ex => ReferenceReplacingExpressionVisitor
                    .ReplaceClauseReferences(ex, innerSelectorMapping, false));

                InsertBodyClauses(subQueryExpression.QueryModel.BodyClauses, queryModel, destinationIndex);

                foreach (var resultOperator in subQueryModel.ResultOperators.Reverse())
                {
                    queryModel.ResultOperators.Insert(0, resultOperator);
                }

                var innerBodyClauseMapping = new QuerySourceMapping();

                innerBodyClauseMapping
                .AddMapping(innerMainFromClause, new QuerySourceReferenceExpression(fromClause));

                queryModel.TransformExpressions(
                    ex => ReferenceReplacingExpressionVisitor
                    .ReplaceClauseReferences(ex, innerBodyClauseMapping, false));

                foreach (var queryAnnotation
                         in _queryAnnotations
                         .Where(qa => qa.QuerySource == subQueryExpression.QueryModel.MainFromClause))
                {
                    queryAnnotation.QuerySource = fromClause;
                    queryAnnotation.QueryModel  = queryModel;
                }
            }
        }