示例#1
0
        public static IQueryable <Entity> TranslateQueryExpressionToLinq(XrmFakedContext context, QueryExpression qe)
        {
            if (qe == null)
            {
                return(null);
            }

            //Start form the root entity and build a LINQ query to execute the query against the In-Memory context:
            context.EnsureEntityNameExistsInMetadata(qe.EntityName);

            IQueryable <Entity> query = null;

            query = context.CreateQuery <Entity>(qe.EntityName);

            //Add as many Joins as linked entities
            foreach (LinkEntity le in qe.LinkEntities)
            {
                query = TranslateLinkedEntityToLinq(context, le, query, qe.ColumnSet);
            }

            // Compose the expression tree that represents the parameter to the predicate.
            ParameterExpression entity = Expression.Parameter(typeof(Entity));
            var expTreeBody            = TranslateQueryExpressionFiltersToExpression(qe, entity);
            Expression <Func <Entity, bool> > lambda = Expression.Lambda <Func <Entity, bool> >(expTreeBody, entity);

            query = query.Where(lambda);

            //Project the attributes in the root column set  (must be applied after the where clause, not before!!)
            query = query.Select(x => x.ProjectAttributes(qe, context));

            //Sort results
            if (qe.Orders != null)
            {
                foreach (var order in qe.Orders)
                {
                    if (order.OrderType == OrderType.Ascending)
                    {
                        query = query.OrderBy(e => e.Attributes.ContainsKey(order.AttributeName) ? e.Attributes[order.AttributeName] : null, new XrmOrderByAttributeComparer());
                    }
                    else
                    {
                        query = query.OrderByDescending(e => e.Attributes.ContainsKey(order.AttributeName) ? e.Attributes[order.AttributeName] : null, new XrmOrderByAttributeComparer());
                    }
                }
            }

            //Apply TopCount
            if (qe.TopCount != null)
            {
                query = query.Take(qe.TopCount.Value);
            }
            return(query);
        }
示例#2
0
        public static IQueryable <Entity> TranslateLinkedEntityToLinq(XrmFakedContext context, LinkEntity le, IQueryable <Entity> query, ColumnSet previousColumnSet, string linkFromAlias = "")
        {
            var leAlias = string.IsNullOrWhiteSpace(le.EntityAlias) ? le.LinkToEntityName : le.EntityAlias;

            context.EnsureEntityNameExistsInMetadata(le.LinkFromEntityName);
            context.EnsureEntityNameExistsInMetadata(le.LinkToEntityName);

            if (!context.AttributeExistsInMetadata(le.LinkToEntityName, le.LinkToAttributeName))
            {
                OrganizationServiceFaultQueryBuilderNoAttributeException.Throw(le.LinkToAttributeName);
            }

            var inner = context.CreateQuery <Entity>(le.LinkToEntityName);

            //if (!le.Columns.AllColumns && le.Columns.Columns.Count == 0)
            //{
            //    le.Columns.AllColumns = true;   //Add all columns in the joined entity, otherwise we can't filter by related attributes, then the Select will actually choose which ones we need
            //}

            if (string.IsNullOrWhiteSpace(linkFromAlias))
            {
                linkFromAlias = le.LinkFromAttributeName;
            }
            else
            {
                linkFromAlias += "." + le.LinkFromAttributeName;
            }

            switch (le.JoinOperator)
            {
            case JoinOperator.Inner:
            case JoinOperator.Natural:
                query = query.Join(inner,
                                   outerKey => outerKey.KeySelector(linkFromAlias, context),
                                   innerKey => innerKey.KeySelector(le.LinkToAttributeName, context),
                                   (outerEl, innerEl) => outerEl
                                   .JoinAttributes(innerEl, new ColumnSet(true), leAlias, context));

                break;

            case JoinOperator.LeftOuter:
                query = query.GroupJoin(inner,
                                        outerKey => outerKey.KeySelector(le.LinkFromAttributeName, context),
                                        innerKey => innerKey.KeySelector(le.LinkToAttributeName, context),
                                        (outerEl, innerElemsCol) => new { outerEl, innerElemsCol })
                        .SelectMany(x => x.innerElemsCol.DefaultIfEmpty()
                                    , (x, y) => x.outerEl
                                    .JoinAttributes(y, new ColumnSet(true), leAlias, context));


                break;

            default:     //This shouldn't be reached as there are only 3 types of Join...
                throw new PullRequestException(string.Format("The join operator {0} is currently not supported. Feel free to implement and send a PR.", le.JoinOperator));
            }

            //Process nested linked entities recursively
            foreach (LinkEntity nestedLinkedEntity in le.LinkEntities)
            {
                if (string.IsNullOrWhiteSpace(le.EntityAlias))
                {
                    le.EntityAlias = le.LinkToEntityName;
                }

                query = TranslateLinkedEntityToLinq(context, nestedLinkedEntity, query, le.Columns, le.EntityAlias);
            }
            return(query);
        }