Beispiel #1
0
        /// <summary>
        /// Gets the relationship values for a single relationship on a single entity.
        /// </summary>
        private static IEnumerable <long> GetRelationshipsImpl(Context context, IEntityRef relTypeId, Direction direction, long entityId)
        {
            long relTypeIdWithDir = relTypeId.Id;

            if (direction == Direction.Reverse)
            {
                relTypeIdWithDir = -relTypeIdWithDir;
            }

            RelationshipKey key = new RelationshipKey(entityId, relTypeIdWithDir);
            List <long>     relList;

            if (!context.RawData.Relationships.TryGetValue(key, out relList))
            {
                return(Enumerable.Empty <long>());
            }

            return(relList);
        }
        /// <summary>
        /// Creates an entity ref for the ID to be checked.
        /// </summary>
        /// <remarks>
        /// The BulkRequestResult graph typically already has type information for the entities being loaded.
        /// The security engine requires type information to determine applicable rules.
        /// So instead of having it attempt to activate the entities (additional DB trips) to determine the types, just
        /// pass the type information along instead.
        /// This is done by creating a EntityTypeOnly implementation of IEntity, and packing it into the EntityRef that we pass.
        /// </remarks>
        /// <param name="data"></param>
        /// <param name="entityId"></param>
        /// <returns></returns>
        private static EntityRef CreateEntityRefForSecurityCheck(BulkRequestResult data, long entityId)
        {
            EntityRef result;
            long      isOfTypeRelId = WellKnownAliases.CurrentTenant.IsOfType;

            // Look up type information
            RelationshipKey key = new RelationshipKey(entityId, isOfTypeRelId);

            List <long> typeIds;

            if (data.Relationships.TryGetValue(key, out typeIds))
            {
                IEntity entity = new EntityTypeOnly(entityId, typeIds);
                result = new EntityRef(entity);
            }
            else
            {
                result = new EntityRef(entityId);
            }

            return(result);
        }
Beispiel #3
0
        /// <summary>
        /// Remove duplicate entries from relationship lists.
        /// (that could result if two different nodes point to the same node along the same relationship)
        /// </summary>
        /// <param name="result"></param>
        private static void RemoveDuplicateRelationshipEntries(BulkRequestResult result)
        {
            // Note: this is a bit messy
            // Ideally we could remove the duplicates during the main ReadRelationships loop.
            // However, I don't want to return the result sorted, as it will unnecessarily slow down the SQL.
            // And I don't want to store individual HashSets in the object if I can help it.

            foreach (var pair in result.Relationships)
            {
                RelationshipKey key             = pair.Key;
                List <long>     targetEntityIds = pair.Value;

                // Only consolidate if there are multiple entries
                // (And do so, without recreating the list, otherwise we'll break our enumeration)
                if (targetEntityIds.Count > 1)
                {
                    HashSet <long> distinct = new HashSet <long>(targetEntityIds);
                    targetEntityIds.Clear( );
                    targetEntityIds.AddRange(distinct);
                }
            }
        }
Beispiel #4
0
        /// <summary>
        /// Read relationships, and top level entities, from the database result.
        /// </summary>
        private static void ReadRelationships(IDataReader reader, BulkSqlQuery query, BulkRequestResult result)
        {
            // select distinct EntityId, RelSrcId, RelTypeId from #process
            while (reader.Read())
            {
                // Caution: We're in a database-read context, so don't touch the entity model or things will crash.

                long toId          = reader.GetInt64(0);
                int  nodeTag       = reader.GetInt32(1);    // tag of the request node that returned this entity
                long fromId        = reader.GetInt64(2);    // zero for root-level entities
                long typeIdWithNeg = reader.GetInt64(3);    // relationship type-id, with reverse being indicated with negative values

                // Root result entity
                if (fromId == 0)
                {
                    result.RootEntities.Add(toId);
                }
                else
                {
                    // Add to dictionary
                    var key   = new RelationshipKey(fromId, typeIdWithNeg);
                    var value = toId;

                    List <long> list;
                    if (!result.Relationships.TryGetValue(key, out list))
                    {
                        list = new List <long>();
                        result.Relationships[key] = list;
                    }
                    list.Add(value);
                }

                // Implicit relationship security
                bool implicitlySecured = false;
                if (fromId != 0)
                {
                    var relInfo = query.Relationships[typeIdWithNeg];
                    implicitlySecured = relInfo.ImpliesSecurity;
                }

                // Store entity
                EntityValue ev;
                if (!result.AllEntities.TryGetValue(toId, out ev))
                {
                    ev = new EntityValue {
                        ImplicitlySecured = implicitlySecured
                    };
                    result.AllEntities[toId] = ev;
                }
                else
                {
                    ev.ImplicitlySecured = ev.ImplicitlySecured && implicitlySecured;
                }

                // Store the request node that specified members to load for this entity
                RequestNodeInfo requestNode = query.RequestNodes [nodeTag];
                ev.Nodes.Add(requestNode);
            }

#if DEBUG
            if (result.RootEntitiesList.Count != 0)
            {
                throw new InvalidOperationException("Assert false .. expected RootEntityList to be empty.");
            }
#endif
            result.RootEntitiesList.AddRange(result.RootEntities);

            RemoveDuplicateRelationshipEntries(result);
        }