Esempio n. 1
0
        /// <summary>
        /// Extension method to join the attributes of entity e and otherEntity
        /// </summary>
        /// <param name="e"></param>
        /// <param name="otherEntity"></param>
        /// <param name="attributes"></param>
        /// <returns></returns>
        public static Entity JoinAttributes(this Entity e, Entity otherEntity, ColumnSet columnSet, string alias, XrmFakedContext context)
        {
            if (otherEntity == null)
            {
                return(e);                     //Left Join where otherEntity was not matched
            }
            otherEntity = otherEntity.Clone(); //To avoid joining entities from/to the same entities, which would cause collection modified exceptions

            if (columnSet.AllColumns)
            {
                foreach (var attKey in otherEntity.Attributes.Keys)
                {
                    e[alias + "." + attKey] = new AliasedValue(otherEntity.LogicalName, attKey, otherEntity[attKey]);
                }

                foreach (var attKey in otherEntity.FormattedValues.Keys)
                {
                    e.FormattedValues[alias + "." + attKey] = otherEntity.FormattedValues[attKey];
                }
            }
            else
            {
                //Return selected list of attributes
                foreach (var attKey in columnSet.Columns)
                {
                    if (!context.AttributeExistsInMetadata(otherEntity.LogicalName, attKey))
                    {
                        OrganizationServiceFaultQueryBuilderNoAttributeException.Throw(attKey);
                    }

                    if (otherEntity.Attributes.ContainsKey(attKey))
                    {
                        e[alias + "." + attKey] = new AliasedValue(otherEntity.LogicalName, attKey, otherEntity[attKey]);
                    }
                    else
                    {
                        e[alias + "." + attKey] = new AliasedValue(otherEntity.LogicalName, attKey, null);
                    }

                    if (otherEntity.FormattedValues.ContainsKey(attKey))
                    {
                        e.FormattedValues[alias + "." + attKey] = otherEntity.FormattedValues[attKey];
                    }
                }
            }
            return(e);
        }
Esempio n. 2
0
        public static Entity ProjectAttributes(this Entity e, QueryExpression qe, XrmFakedContext context)
        {
            if (qe.ColumnSet == null)
            {
                return(e);
            }

            if (qe.ColumnSet.AllColumns)
            {
                return(e); //return all the original attributes
            }
            else
            {
                //Return selected list of attributes in a projected entity
                Entity projected = null;

                //However, if we are using proxy types, we must create a instance of the appropiate class
                if (context.ProxyTypesAssembly != null)
                {
                    var subClassType = context.FindReflectedType(e.LogicalName);
                    if (subClassType != null)
                    {
                        var instance = Activator.CreateInstance(subClassType);
                        projected    = (Entity)instance;
                        projected.Id = e.Id;
                    }
                    else
                    {
                        projected = new Entity(e.LogicalName)
                        {
                            Id = e.Id
                        }
                    };                                                       //fallback to generic type if type not found
                }
                else
                {
                    projected = new Entity(e.LogicalName)
                    {
                        Id = e.Id
                    }
                };

                foreach (var attKey in qe.ColumnSet.Columns)
                {
                    //Check if attribute really exists in metadata
                    if (!context.AttributeExistsInMetadata(e.LogicalName, attKey))
                    {
                        OrganizationServiceFaultQueryBuilderNoAttributeException.Throw(attKey);
                    }

                    if (e.Attributes.ContainsKey(attKey) && e.Attributes[attKey] != null)
                    {
                        projected[attKey] = CloneAttribute(e[attKey]);
                    }
                }

                //Plus attributes from joins
                foreach (var le in qe.LinkEntities)
                {
                    ProjectAttributes(e, projected, le, context);
                }
                //foreach (var attKey in e.Attributes.Keys)
                //{
                //    if(e[attKey] is AliasedValue && !projected.Attributes.ContainsKey(attKey))
                //        projected[attKey] = e[attKey];
                //}
                return(projected);
            }
        }
Esempio n. 3
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);
        }