Beispiel #1
0
        /// <summary>
        /// Determine if two relationship data refer to the same relationship in the same direction.
        /// </summary>
        private static bool SameRelationship(RelationshipData rel1, RelationshipData rel2)
        {
            if (rel1.RelationshipTypeId.Id != rel2.RelationshipTypeId.Id)
            {
                return(false);
            }

            var dir1 = Entity.GetDirection(rel1.RelationshipTypeId, rel1.IsReverse);
            var dir2 = Entity.GetDirection(rel2.RelationshipTypeId, rel2.IsReverse);

            return(dir1 == dir2);
        }
Beispiel #2
0
        /// <summary>
        /// Populates the relationships for an EntityData. Recursively load entities.
        /// </summary>
        /// <param name="context">Overall request context.</param>
        /// <param name="request">Current request node to be loaded.</param>
        /// <param name="entity">Source entity to get the field data from.</param>
        /// <param name="entityData">Target entityData to store field data into.</param>
        /// <param name="isNew">Flag indicating that EntityData is fresh, so we don't need to worry about checking if data is already loaded.</param>
        private void PackageEntityRelationships(Context context, EntityMemberRequest request, TEntity entity, EntityData entityData, bool isNew)
        {
            // Overall process:
            // - determine list of fields to load for this request
            // - determine if a particular field has already been loaded
            // - get the fields from entity
            // - store the field in entityData

            // Prepare container
            if (isNew)
            {
                entityData.Relationships = new List <RelationshipData>();
            }


            // Translate relationships
            foreach (RelationshipRequest relReq in request.Relationships)
            {
                // Establish relationship identity and direction
                Direction direction = Entity.GetDirection(relReq.RelationshipTypeId, relReq.IsReverse);

                // Create object to represent results for this relationship type
                // Note: immediately register the relationship, as this method is re-entrant.
                var relData = new RelationshipData();
                relData.RelationshipTypeId = relReq.RelationshipTypeId;
                relData.IsReverse          = relReq.IsReverse;
                relData.IsReverseActual    = direction == Direction.Reverse;
                relData.IsLookup           = GetIsLookup(relReq.RelationshipTypeId, direction);

                // Hmm.. we may be processing the same relationship twice, via different member requests.
                // We need to do this so that any additional members get loaded on the related entities, but we don't want to
                // include the relationship list twice, so just remove the existing. (This is a bit hacky)
                entityData.Relationships.RemoveAll(r => SameRelationship(r, relData));
                entityData.Relationships.Add(relData);

                if (relReq.MetadataOnly)
                {
                    relData.Instances = new List <RelationshipInstanceData>();
                }
                else
                {
                    // Get the list of related entities from the entity model
                    var relationshipsRaw = GetRelationships(entity, relReq.RelationshipTypeId, direction);

                    var relationships = relationshipsRaw
                                        .Where(p => !Equals(p, default(TEntity)))
                                        .Take(FanoutHelper.MaxRelatedEntities + 1)
                                        .ToList();

                    // Throttle list size
                    if (!BulkPreloader.TenantWarmupRunning)
                    {
                        int relCount = relationships.Count;
                        FanoutHelper.CheckFanoutLimit(relReq, GetId(entity), relCount);
                    }

                    // Split lists
                    var entityList = relationships.Select(p => p);

                    // Package related entities and relationship instances
                    var entities = PackageEntities(context, relReq.RequestedMembers, entityList);

                    // Convert results into RelationshipInstanceData list
                    relData.Instances = entities.Select(relatedEntity =>
                                                        new RelationshipInstanceData()
                    {
                        Entity = relatedEntity
                    })
                                        .Where(rid => rid.Entity != null)
                                        .ToList();

                    // Rerun again with recursive request (note: this will fill into the existing entities)
                    if (relReq.IsRecursive)
                    {
                        var tmpEnum = PackageEntities(context, request, entityList);
                        ForceVisitAll(tmpEnum);
                    }
                }
            }
        }