Beispiel #1
0
        /// <summary>
        /// Additional processing required for server deserialization. Flags a
        /// processed attribute or relationship as updated using <see cref="ITargetedFields"/>.
        /// </summary>
        /// <param name="resource">The resource that was constructed from the document's body.</param>
        /// <param name="field">The metadata for the exposed field.</param>
        /// <param name="data">Relationship data for <paramref name="resource"/>. Is null when <paramref name="field"/> is not a <see cref="RelationshipAttribute"/>.</param>
        protected override void AfterProcessField(IIdentifiable resource, ResourceFieldAttribute field,
                                                  RelationshipEntry data = null)
        {
            bool isCreatingResource = IsCreatingResource();
            bool isUpdatingResource = IsUpdatingResource();

            if (field is AttrAttribute attr)
            {
                if (isCreatingResource && !attr.Capabilities.HasFlag(AttrCapabilities.AllowCreate))
                {
                    throw new JsonApiSerializationException(
                              "Setting the initial value of the requested attribute is not allowed.",
                              $"Setting the initial value of '{attr.PublicName}' is not allowed.",
                              atomicOperationIndex: AtomicOperationIndex);
                }

                if (isUpdatingResource && !attr.Capabilities.HasFlag(AttrCapabilities.AllowChange))
                {
                    throw new JsonApiSerializationException(
                              "Changing the value of the requested attribute is not allowed.",
                              $"Changing the value of '{attr.PublicName}' is not allowed.",
                              atomicOperationIndex: AtomicOperationIndex);
                }

                _targetedFields.Attributes.Add(attr);
            }
            else if (field is RelationshipAttribute relationship)
            {
                _targetedFields.Relationships.Add(relationship);
            }
        }
Beispiel #2
0
        /// <summary>
        ///     Gets the missing relationships.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <returns></returns>
        public IEnumerable <RelationshipEntry> GetMissingRelationships(IProcessingContext context)
        {
            long tenantId = CallData <long> .GetValue("TargetTenantId");

            Dictionary <Guid, CardinalityEnum_Enumeration> typeCardinalities = TypeCardinalities;

            /////
            // Query entities that are part of the solution
            /////
            const string sql = @"SELECT TypeUid, FromUid, ToUid FROM AppDeploy_Relationship WHERE AppVerUid = @appVer AND TenantId = @tenantId";

            using (IDbCommand command = CreateCommand( ))
            {
                command.CommandText = sql;
                command.AddParameterWithValue("@appVer", AppVerId);
                command.AddParameterWithValue("@tenantId", tenantId);

                using (IDataReader reader = command.ExecuteReader( ))
                {
                    while (reader.Read( ))
                    {
                        Guid typeId = reader.GetGuid(0);
                        Guid fromId = reader.GetGuid(1);
                        Guid toId   = reader.GetGuid(2);

                        CardinalityEnum_Enumeration cardinality;

                        RelationshipEntry entry = typeCardinalities.TryGetValue(typeId, out cardinality) ? new RelationshipEntry(typeId, fromId, toId, cardinality) : new RelationshipEntry(typeId, fromId, toId);

                        yield return(entry);
                    }
                }
            }
        }
Beispiel #3
0
        /// <summary>
        /// Builds the values of the relationships object on a resource object.
        /// The server serializer only populates the "data" member when the relationship is included,
        /// and adds links unless these are turned off. This means that if a relationship is not included
        /// and links are turned off, the entry would be completely empty, ie { }, which is not conform
        /// json:api spec. In that case we return null which will omit the entry from the output.
        /// </summary>
        protected override RelationshipEntry GetRelationshipData(RelationshipAttribute relationship, IIdentifiable entity)
        {
            RelationshipEntry relationshipEntry = null;
            List <List <RelationshipAttribute> > relationshipChains = null;

            if (relationship == _requestRelationship || ShouldInclude(relationship, out relationshipChains))
            {
                relationshipEntry = base.GetRelationshipData(relationship, entity);
                if (relationshipChains != null && relationshipEntry.HasResource)
                {
                    foreach (var chain in relationshipChains)
                    {
                        // traverses (recursively) and extracts all (nested) related entities for the current inclusion chain.
                        _includedBuilder.IncludeRelationshipChain(chain, entity);
                    }
                }
            }

            var links = _linkBuilder.GetRelationshipLinks(relationship, entity);

            if (links != null)
            {
                // if links relationshipLinks should be built for this entry, populate the "links" field.
                (relationshipEntry = relationshipEntry ?? new RelationshipEntry()).Links = links;
            }

            // if neither "links" nor "data" was popupated, return null, which will omit this entry from the output.
            // (see the NullValueHandling settings on <see cref="ResourceObject"/>)
            return(relationshipEntry);
        }
Beispiel #4
0
        /// <summary>
        /// Sets a HasOne relationship on a parsed entity. If present, also
        /// populates the foreign key.
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="entityProperties"></param>
        /// <param name="attr"></param>
        /// <param name="relationshipData"></param>
        /// <returns></returns>
        private object SetHasOneRelationship(IIdentifiable entity,
                                             PropertyInfo[] entityProperties,
                                             HasOneAttribute attr,
                                             RelationshipEntry relationshipData)
        {
            var rio       = (ResourceIdentifierObject)relationshipData.Data;
            var relatedId = rio?.Id ?? null;

            // this does not make sense in the following case: if we're setting the dependent of a one-to-one relationship, IdentifiablePropertyName should be null.
            var foreignKeyProperty = entityProperties.FirstOrDefault(p => p.Name == attr.IdentifiablePropertyName);

            if (foreignKeyProperty != null)
            {
                /// there is a FK from the current entity pointing to the related object,
                /// i.e. we're populating the relationship from the dependent side.
                SetForeignKey(entity, foreignKeyProperty, attr, relatedId);
            }

            SetNavigation(entity, attr, relatedId);

            /// depending on if this base parser is used client-side or server-side,
            /// different additional processing per field needs to be executed.
            AfterProcessField(entity, attr, relationshipData);

            return(entity);
        }
Beispiel #5
0
        /// <summary>
        /// Sets a HasOne relationship on a parsed resource. If present, also
        /// populates the foreign key.
        /// </summary>
        private void SetHasOneRelationship(IIdentifiable resource,
                                           PropertyInfo[] resourceProperties,
                                           HasOneAttribute attr,
                                           RelationshipEntry relationshipData)
        {
            var rio       = (ResourceIdentifierObject)relationshipData.Data;
            var relatedId = rio?.Id;

            var relationshipType = relationshipData.SingleData == null
                ? attr.RightType
                : ResourceContextProvider.GetResourceContext(relationshipData.SingleData.Type).ResourceType;

            // this does not make sense in the following case: if we're setting the dependent of a one-to-one relationship, IdentifiablePropertyName should be null.
            var foreignKeyProperty = resourceProperties.FirstOrDefault(p => p.Name == attr.IdentifiablePropertyName);

            if (foreignKeyProperty != null)
            {
                // there is a FK from the current resource pointing to the related object,
                // i.e. we're populating the relationship from the dependent side.
                SetForeignKey(resource, foreignKeyProperty, attr, relatedId, relationshipType);
            }

            SetNavigation(resource, attr, relatedId, relationshipType);

            // depending on if this base parser is used client-side or server-side,
            // different additional processing per field needs to be executed.
            AfterProcessField(resource, attr, relationshipData);
        }
Beispiel #6
0
        /// <summary>
        /// This is the implementation API for returning relationships. The default implementation stores the
        /// relationship in a table. Relationships are stored weakly, so they do not keep an object alive. Empty can be
        /// passed in for relationship to remove the relationship.
        /// </summary>
        protected virtual void SetRelationship(MemberRelationship source, MemberRelationship relationship)
        {
            if (!relationship.IsEmpty && !SupportsRelationship(source, relationship))
            {
                ThrowRelationshipNotSupported(source, relationship);
            }

            _relationships[new RelationshipEntry(source)] = new RelationshipEntry(relationship);
        }
        /// <summary>
        ///     Handle case if one entity is a component of the other.
        /// </summary>
        /// <param name="relType">The relationship type.</param>
        /// <param name="fromEntity">The 'from' entity.</param>
        /// <param name="toEntity">The 'to' entity.</param>
        /// <returns></returns>
        private bool HandleContainedEntities(RelationshipEntry rel, RelationshipTypeEntry relType, EntityHierarchyEntry fromEntity, EntityHierarchyEntry toEntity)
        {
            if (relType == null)
            {
                return(false);
            }

            // Explicitly do not next certain relationships
            if (rel.TypeId == Guids.InSolution || rel.TypeId == Guids.IndirectInSolution)
            {
                return(false);
            }

            // if 'fwdComponent' then parent = FromId
            // if 'revComponent' then parent = ToId
            // "Clone action" is the best proxy to determine if something is a subcomponent, while still handling 'custom' reltypes.
            bool fwdComponent = relType.CloneAction == CloneActionEnum_Enumeration.CloneEntities;
            bool revComponent = !fwdComponent && relType.ReverseCloneAction == CloneActionEnum_Enumeration.CloneEntities;

            EntityHierarchyEntry parent = null;
            EntityHierarchyEntry child  = null;

            if (fwdComponent)
            {
                parent = fromEntity;
                child  = toEntity;
            }
            else if (revComponent)
            {
                parent = toEntity;
                child  = fromEntity;
            }
            else
            {
                return(false);
            }

            if (child.ParentEntity != null)
            {
                return(false);   // child already assigned to a different parent
            }
            if (WouldCauseCycle(parent, child))
            {
                return(false);
            }

            if (parent.Children == null)
            {
                parent.Children = new List <EntityHierarchyEntry>( );
            }
            parent.Children.Add(child);
            child.ParentEntity           = parent;
            child.RelationshipFromParent = rel;
            child.Direction = revComponent ? Direction.Reverse : Direction.Forward;
            return(true);
        }
            public override bool Equals(object o)
            {
                if (o is RelationshipEntry)
                {
                    RelationshipEntry e = (RelationshipEntry)o;
                    return(this == e);
                }

                return(false);
            }
        /// <summary>
        /// Puts the relationships of the resource into the resource object.
        /// </summary>
        private void ProcessRelationships(IIdentifiable resource, IEnumerable <RelationshipAttribute> relationships, ResourceObject ro)
        {
            foreach (RelationshipAttribute rel in relationships)
            {
                RelationshipEntry relData = GetRelationshipData(rel, resource);

                if (relData != null)
                {
                    (ro.Relationships ??= new Dictionary <string, RelationshipEntry>()).Add(rel.PublicName, relData);
                }
            }
        }
 /// <summary>
 ///     Serializes the relationship.
 /// </summary>
 /// <param name="xmlWriter">The XML writer.</param>
 /// <param name="relationship">The relationship.</param>
 /// <param name="defaultTypeName">Default name of the type.</param>
 /// <param name="xmlStack">The XML stack.</param>
 private void SerializeRelationship(XmlWriter xmlWriter, RelationshipEntry relationship, Stack <string> xmlStack)
 {
     using (WriteElementBlock(xmlWriter, relationship.TypeId, XmlConstants.RelationshipConstants.Rel, XmlConstants.RelationshipConstants.Rel, XmlConstants.Id, xmlStack))
     {
         using (xmlWriter.WriteElementBlock(XmlConstants.RelationshipConstants.From, xmlStack))
         {
             xmlWriter.WriteString(GetInnerText(relationship.FromId));
         }
         using (xmlWriter.WriteElementBlock(XmlConstants.RelationshipConstants.To, xmlStack))
         {
             xmlWriter.WriteString(GetInnerText(relationship.ToId));
         }
     }
 }
        private void ExcludeEntityKey()
        {
            RelationshipEntry relationship = this.ObjectContext.ObjectStateManager.FindRelationship(this.RelationshipSet, new KeyValuePair <string, EntityKey>(this.RelationshipNavigation.From, this.WrappedOwner.EntityKey), new KeyValuePair <string, EntityKey>(this.RelationshipNavigation.To, this.DetachedEntityKey));

            if (relationship == null)
            {
                return;
            }
            relationship.Delete(false);
            if (relationship.State == EntityState.Detached)
            {
                return;
            }
            relationship.AcceptChanges();
        }
Beispiel #12
0
        protected RelationshipEntry CreateRelationshipData(string relatedType = null, bool isToManyData = false, string id = "10")
        {
            var entry = new RelationshipEntry();
            var rio   = relatedType == null ? null : new ResourceIdentifierObject {
                Id = id, Type = relatedType
            };

            if (isToManyData)
            {
                entry.Data = relatedType != null?rio.AsList() : new List <ResourceIdentifierObject>();
            }
            else
            {
                entry.Data = rio;
            }
            return(entry);
        }
Beispiel #13
0
        /// <summary>
        /// Builds the values of the relationships object on a resource object.
        /// The server serializer only populates the "data" member when the relationship is included,
        /// and adds links unless these are turned off. This means that if a relationship is not included
        /// and links are turned off, the entry would be completely empty, ie { }, which is not conform
        /// JSON:API spec. In that case we return null which will omit the entry from the output.
        /// </summary>
        protected override RelationshipEntry GetRelationshipData(RelationshipAttribute relationship, IIdentifiable resource)
        {
            if (relationship == null)
            {
                throw new ArgumentNullException(nameof(relationship));
            }
            if (resource == null)
            {
                throw new ArgumentNullException(nameof(resource));
            }

            RelationshipEntry relationshipEntry = null;
            List <IReadOnlyCollection <RelationshipAttribute> > relationshipChains = null;

            if (Equals(relationship, _requestRelationship) || ShouldInclude(relationship, out relationshipChains))
            {
                relationshipEntry = base.GetRelationshipData(relationship, resource);
                if (relationshipChains != null && relationshipEntry.HasResource)
                {
                    foreach (var chain in relationshipChains)
                    {
                        // traverses (recursively) and extracts all (nested) related resources for the current inclusion chain.
                        _includedBuilder.IncludeRelationshipChain(chain, resource);
                    }
                }
            }

            if (!IsRelationshipInSparseFieldSet(relationship))
            {
                return(null);
            }

            var links = _linkBuilder.GetRelationshipLinks(relationship, resource);

            if (links != null)
            {
                // if relationshipLinks should be built for this entry, populate the "links" field.
                relationshipEntry ??= new RelationshipEntry();
                relationshipEntry.Links = links;
            }

            // if neither "links" nor "data" was populated, return null, which will omit this entry from the output.
            // (see the NullValueHandling settings on <see cref="ResourceObject"/>)
            return(relationshipEntry);
        }
        public void Setting_ExposeData_To_RIO_Sets_SingleData()
        {
            // Arrange
            var relationshipData = new RelationshipEntry();
            var relationship     = new ResourceIdentifierObject {
                Id   = "9",
                Type = "authors"
            };

            // Act
            relationshipData.Data = relationship;

            // Assert
            Assert.NotNull(relationshipData.SingleData);
            Assert.Equal("authors", relationshipData.SingleData.Type);
            Assert.Equal("9", relationshipData.SingleData.Id);
            Assert.False(relationshipData.IsManyData);
        }
Beispiel #15
0
        /// <summary>
        ///     Serializes the inline relationship.
        /// </summary>
        /// <param name="xmlWriter">The XML writer.</param>
        /// <param name="relationship">The relationship.</param>
        /// <param name="defaultElementName">Default name of the element.</param>
        /// <param name="xmlStack">The XML stack.</param>
        private void SerializeInlineRelationship(XmlWriter xmlWriter, RelationshipEntry relationship, string defaultElementName, Stack <string> xmlStack)
        {
            string elementName;
            string nameSpace;

            bool resolved = TryGetElementName(relationship.TypeId, out elementName, out nameSpace);

            xmlWriter.WriteStartElement(elementName ?? defaultElementName, nameSpace, xmlStack);

            if (!resolved)
            {
                xmlWriter.WriteAttributeString(XmlConstants.Id, relationship.TypeId.ToString("B"));
            }

            xmlWriter.WriteString(GetInnerText(relationship.ToId));

            xmlWriter.WriteEndElement(elementName ?? defaultElementName, xmlStack);
        }
        private void ExcludeEntityKey()
        {
            EntityKey ownerKey = WrappedOwner.EntityKey;

            RelationshipEntry relationshipEntry = this.ObjectContext.ObjectStateManager.FindRelationship(RelationshipSet,
                                                                                                         new KeyValuePair <string, EntityKey>(RelationshipNavigation.From, ownerKey),
                                                                                                         new KeyValuePair <string, EntityKey>(RelationshipNavigation.To, DetachedEntityKey));

            // we may have failed in adding the graph before we actually added this relationship, so make sure we actually found one
            if (relationshipEntry != null)
            {
                relationshipEntry.Delete(/*doFixup*/ false);
                // If entry was Added before, it is now Detached, otherwise AcceptChanges to detach it
                if (relationshipEntry.State != EntityState.Detached)
                {
                    relationshipEntry.AcceptChanges();
                }
            }
        }
Beispiel #17
0
        /// <summary>
        /// Sets a HasMany relationship.
        /// </summary>
        private void SetHasManyRelationship(
            IIdentifiable entity,
            HasManyAttribute attr,
            RelationshipEntry relationshipData)
        {
            if (relationshipData.Data != null)
            {   // if the relationship is set to null, no need to set the navigation property to null: this is the default value.
                var relatedResources = relationshipData.ManyData.Select(rio =>
                {
                    var relatedInstance      = attr.RightType.New <IIdentifiable>();
                    relatedInstance.StringId = rio.Id;
                    return(relatedInstance);
                });
                var convertedCollection = relatedResources.Cast(attr.RightType);
                attr.SetValue(entity, convertedCollection);
            }

            AfterProcessField(entity, attr, relationshipData);
        }
Beispiel #18
0
        /// <summary>
        ///     Load relationships.
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public IEnumerable <RelationshipEntry> GetRelationships(IProcessingContext context)
        {
            /////
            // Query entities that are part of the solution
            /////
            const string sql = @"select TypeUid, FromUid, ToUid from _Relationship r";

            using (IDbCommand command = CreateCommand( ))
            {
                command.CommandText = sql;

                using (IDataReader reader = command.ExecuteReader( ))
                {
                    while (reader.Read( ))
                    {
                        Guid?typeId = GetGuid(reader, 0);

                        if (typeId == null)
                        {
                            continue;
                        }

                        Guid?fromId = GetGuid(reader, 1);

                        if (fromId == null)
                        {
                            continue;
                        }

                        Guid?toId = GetGuid(reader, 2);

                        if (toId == null)
                        {
                            continue;
                        }

                        RelationshipEntry entry = new RelationshipEntry(typeId.Value, fromId.Value, toId.Value);

                        yield return(entry);
                    }
                }
            }
        }
Beispiel #19
0
        /// <summary>
        /// This is the implementation API for returning relationships. The default implementation stores the
        /// relationship in a table. Relationships are stored weakly, so they do not keep an object alive. Empty can be
        /// passed in for relationship to remove the relationship.
        /// </summary>
        protected virtual void SetRelationship(MemberRelationship source, MemberRelationship relationship)
        {
            if (!relationship.IsEmpty && !SupportsRelationship(source, relationship))
            {
                string sourceName = TypeDescriptor.GetComponentName(source.Owner);
                string relName    = TypeDescriptor.GetComponentName(relationship.Owner);
                if (sourceName == null)
                {
                    sourceName = source.Owner.ToString();
                }
                if (relName == null)
                {
                    relName = relationship.Owner.ToString();
                }
                throw new ArgumentException(SR.Format(SR.MemberRelationshipService_RelationshipNotSupported, sourceName, source.Member.Name, relName, relationship.Member.Name));
            }

            _relationships[new RelationshipEntry(source)] = new RelationshipEntry(relationship);
        }
Beispiel #20
0
        /// <summary>
        ///     Load relationships.
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        IEnumerable <RelationshipEntry> IDataSource.GetRelationships(IProcessingContext context)
        {
            if (_relationshipCache == null)
            {
                var data = new List <RelationshipEntry>( );

                /////
                // Query entities that are part of the solution
                /////
                using (IDbCommand command = CreateCommand( ))
                {
                    command.CommandText = CommandText.TenantSourceGetRelationshipsCommandText;
                    command.CommandType = CommandType.Text;
                    command.AddParameterWithValue("@tenant", TenantId);

                    using (IDataReader reader = command.ExecuteReader( ))
                    {
                        while (reader.Read( ))
                        {
                            if (reader.IsDBNull(0))
                            {
                                context?.WriteWarning("Unexpected null UpgradeId in Entity.");

                                continue;
                            }

                            Guid typeId = reader.GetGuid(0);
                            Guid fromId = reader.GetGuid(1);
                            Guid toId   = reader.GetGuid(2);

                            RelationshipEntry entry = new RelationshipEntry(typeId, fromId, toId);

                            data.Add(entry);
                        }
                    }
                }

                _relationshipCache = data;
            }

            return(_relationshipCache);
        }
Beispiel #21
0
        /// <summary>
        /// Sets a HasMany relationship.
        /// </summary>
        private void SetHasManyRelationship(
            IIdentifiable resource,
            HasManyAttribute attr,
            RelationshipEntry relationshipData)
        {
            if (relationshipData.Data != null)
            {   // if the relationship is set to null, no need to set the navigation property to null: this is the default value.
                var relatedResources = relationshipData.ManyData.Select(rio =>
                {
                    var relatedInstance      = (IIdentifiable)ResourceFactory.CreateInstance(attr.RightType);
                    relatedInstance.StringId = rio.Id;
                    return(relatedInstance);
                });

                var convertedCollection = TypeHelper.CopyToTypedCollection(relatedResources, attr.Property.PropertyType);
                attr.SetValue(resource, convertedCollection, ResourceFactory);
            }

            AfterProcessField(resource, attr, relationshipData);
        }
        public void Setting_ExposeData_To_List_Sets_ManyData()
        {
            // Arrange
            var relationshipData = new RelationshipEntry();
            var relationships    = new List <ResourceIdentifierObject> {
                new ResourceIdentifierObject {
                    Id   = "9",
                    Type = "authors"
                }
            };

            // Act
            relationshipData.Data = relationships;

            // Assert
            Assert.NotEmpty(relationshipData.ManyData);
            Assert.Equal("authors", relationshipData.ManyData[0].Type);
            Assert.Equal("9", relationshipData.ManyData[0].Id);
            Assert.True(relationshipData.IsManyData);
        }
        public void Setting_ExposeData_To_JObject_Sets_SingleData()
        {
            // Arrange
            var          relationshipData = new RelationshipEntry();
            const string relationshipJson = @"{
                    ""id"": ""9"",
                    ""type"": ""authors""
                }";

            var relationship = JObject.Parse(relationshipJson);

            // Act
            relationshipData.Data = relationship;

            // Assert
            Assert.NotNull(relationshipData.SingleData);
            Assert.Equal("authors", relationshipData.SingleData.Type);
            Assert.Equal("9", relationshipData.SingleData.Id);
            Assert.False(relationshipData.IsManyData);
        }
Beispiel #24
0
        protected RelationshipEntry CreateRelationshipData(string relatedType = null, bool isToManyData = false)
        {
            var data = new RelationshipEntry();
            var rio  = relatedType == null ? null : new ResourceIdentifierObject {
                Id = "10", Type = relatedType
            };

            if (isToManyData)
            {
                data.Data = new List <ResourceIdentifierObject>();
                if (relatedType != null)
                {
                    ((List <ResourceIdentifierObject>)data.Data).Add(rio);
                }
            }
            else
            {
                data.Data = rio;
            }
            return(data);
        }
        /// <summary>
        /// Sets a HasMany relationship.
        /// </summary>
        private void SetHasManyRelationship(
            IIdentifiable resource,
            HasManyAttribute hasManyRelationship,
            RelationshipEntry relationshipData)
        {
            if (relationshipData.ManyData == null)
            {
                throw new JsonApiSerializationException("Expected data[] element for to-many relationship.",
                                                        $"Expected data[] element for '{hasManyRelationship.PublicName}' relationship.");
            }

            var rightResources = relationshipData.ManyData
                                 .Select(rio => CreateRightResource(hasManyRelationship, rio))
                                 .ToHashSet(IdentifiableComparer.Instance);

            var convertedCollection = TypeHelper.CopyToTypedCollection(rightResources, hasManyRelationship.Property.PropertyType);

            hasManyRelationship.SetValue(resource, convertedCollection);

            AfterProcessField(resource, hasManyRelationship, relationshipData);
        }
        public void Setting_ExposeData_To_JArray_Sets_ManyData()
        {
            // Arrange
            var          relationshipData  = new RelationshipEntry();
            const string relationshipsJson = @"[
                {
                    ""type"": ""authors"",
                    ""id"": ""9""
                }
            ]";

            var relationships = JArray.Parse(relationshipsJson);

            // Act
            relationshipData.Data = relationships;

            // Assert
            Assert.NotEmpty(relationshipData.ManyData);
            Assert.Equal("authors", relationshipData.ManyData[0].Type);
            Assert.Equal("9", relationshipData.ManyData[0].Id);
            Assert.True(relationshipData.IsManyData);
        }
 internal override void Exclude()
 {
     if (this._wrappedCachedValue.Entity != null)
     {
         TransactionManager transactionManager = this.ObjectContext.ObjectStateManager.TransactionManager;
         bool doFixup = transactionManager.PopulatedEntityReferences.Contains((EntityReference)this);
         bool flag    = transactionManager.AlignedEntityReferences.Contains((EntityReference)this);
         if ((transactionManager.ProcessedEntities == null || !transactionManager.ProcessedEntities.Contains(this._wrappedCachedValue)) && (doFixup || flag))
         {
             RelationshipEntry relationshipEntry = this.IsForeignKey ? (RelationshipEntry)null : this.FindRelationshipEntryInObjectStateManager(this._wrappedCachedValue);
             this.Remove(this._wrappedCachedValue, doFixup, false, false, false, true);
             if (relationshipEntry != null && relationshipEntry.State != EntityState.Detached)
             {
                 relationshipEntry.AcceptChanges();
             }
             if (doFixup)
             {
                 transactionManager.PopulatedEntityReferences.Remove((EntityReference)this);
             }
             else
             {
                 transactionManager.AlignedEntityReferences.Remove((EntityReference)this);
             }
         }
         else
         {
             this.ExcludeEntity(this._wrappedCachedValue);
         }
     }
     else
     {
         if (!(this.DetachedEntityKey != (EntityKey)null))
         {
             return;
         }
         this.ExcludeEntityKey();
     }
 }
Beispiel #28
0
        /// <summary>
        ///     Serializes the relationship.
        /// </summary>
        /// <param name="xmlWriter">The XML writer.</param>
        /// <param name="relationship">The relationship.</param>
        /// <param name="defaultTypeName">Default name of the type.</param>
        /// <param name="xmlStack">The XML stack.</param>
        private void SerializeRelationship(XmlWriter xmlWriter, RelationshipEntry relationship, string defaultTypeName, Stack <string> xmlStack)
        {
            string typeAlias;
            string typeNamespace;

            bool resolvedType = TryGetElementName(relationship.TypeId, out typeAlias, out typeNamespace);

            xmlWriter.WriteStartElement(typeAlias ?? defaultTypeName, typeNamespace, xmlStack);

            if (!resolvedType)
            {
                xmlWriter.WriteAttributeString(XmlConstants.Id, relationship.TypeId.ToString("B"));
            }

            xmlWriter.WriteStartElement(XmlConstants.RelationshipConstants.From, xmlStack);
            xmlWriter.WriteString(GetInnerText(relationship.FromId));
            xmlWriter.WriteEndElement(XmlConstants.RelationshipConstants.From, xmlStack);

            xmlWriter.WriteStartElement(XmlConstants.RelationshipConstants.To, xmlStack);
            xmlWriter.WriteString(GetInnerText(relationship.ToId));
            xmlWriter.WriteEndElement(XmlConstants.RelationshipConstants.To, xmlStack);

            xmlWriter.WriteEndElement(typeAlias ?? defaultTypeName, xmlStack);
        }
Beispiel #29
0
 protected override void AfterProcessField(IIdentifiable resource, ResourceFieldAttribute field, RelationshipEntry data = null)
 {
 }
 /// <summary>
 ///     Determines whether the specified entry is allowed.
 /// </summary>
 /// <param name="entry">The entry.</param>
 /// <returns></returns>
 public bool IsAllowed(RelationshipEntry entry)
 {
     return(RestrictionCheck(entry));
 }
        /// <devdoc>
        ///    This is the implementation API for returning relationships.  The default implementation stores the 
        ///    relationship in a table.  Relationships are stored weakly, so they do not keep an object alive.  Empty can be
        ///    passed in for relationship to remove the relationship.
        /// </devdoc>
        protected virtual void SetRelationship(MemberRelationship source, MemberRelationship relationship) {

            if (!relationship.IsEmpty && !SupportsRelationship(source, relationship)) {
                string sourceName = TypeDescriptor.GetComponentName(source.Owner);
                string relName = TypeDescriptor.GetComponentName(relationship.Owner);
                if (sourceName == null) {
                    sourceName = source.Owner.ToString();
                }
                if (relName == null) {
                    relName = relationship.Owner.ToString();
                }
                throw new ArgumentException(SR.GetString(SR.MemberRelationshipService_RelationshipNotSupported, sourceName, source.Member.Name, relName, relationship.Member.Name));
            }

            if (_relationships == null) {
                _relationships = new Dictionary<RelationshipEntry,RelationshipEntry>();
            }

            _relationships[new RelationshipEntry(source)] = new RelationshipEntry(relationship);
        }