/// <summary>Creates a new instance of the <see cref="T:Microsoft.OData.Service.Providers.ResourceAssociationSetEnd" /> class.</summary>
        /// <param name="resourceSet">The resource set to which the <see cref="T:Microsoft.OData.Service.Providers.ResourceAssociationSetEnd" /> end belongs.</param>
        /// <param name="resourceType">The resource type to which the <see cref="T:Microsoft.OData.Service.Providers.ResourceAssociationSetEnd" /> end belongs.</param>
        /// <param name="resourceProperty">The resource property that returns the <see cref="T:Microsoft.OData.Service.Providers.ResourceAssociationSetEnd" /> end.</param>
        public ResourceAssociationSetEnd(ResourceSet resourceSet, ResourceType resourceType, ResourceProperty resourceProperty)
        {
            WebUtil.CheckArgumentNull(resourceSet, "resourceSet");
            WebUtil.CheckArgumentNull(resourceType, "resourceType");

            if (resourceProperty != null && (resourceType.TryResolvePropertyName(resourceProperty.Name) == null || resourceProperty.TypeKind != ResourceTypeKind.EntityType))
            {
                throw new ArgumentException(Strings.ResourceAssociationSetEnd_ResourcePropertyMustBeNavigationPropertyOnResourceType);
            }

            if (!resourceSet.ResourceType.IsAssignableFrom(resourceType) && !resourceType.IsAssignableFrom(resourceSet.ResourceType))
            {
                throw new ArgumentException(Strings.ResourceAssociationSetEnd_ResourceTypeMustBeAssignableToResourceSet);
            }

            this.resourceSet = resourceSet;
            this.resourceType = resourceType;

            // Note that for the TargetEnd, resourceProperty can be null.
            this.resourceProperty = resourceProperty;
        }
Exemple #2
0
        /// <summary>Creates new instance of <see cref="ProjectionNode"/> which represents a simple projected property.</summary>
        /// <param name="propertyName">The name of the property to project.</param>
        /// <param name="property">The <see cref="ResourceProperty"/> for the property to project. If an open property
        /// is to be projected, specify null.</param>
        /// <param name="targetResourceType">The resource type for which the <see cref="property"/>needs to be projected.</param>
        internal ProjectionNode(string propertyName, ResourceProperty property, ResourceType targetResourceType)
        {
            Debug.Assert(propertyName != null, "propertyName != null");
            Debug.Assert(property == null || property.Name == propertyName, "If the property is specified its name must match.");
#if DEBUG
            // For rootProjectionNode, there is no targetResourceType. Hence checking for propertyName to be String.Empty to excluse RootProjectionNode from the assert.
            if (!String.IsNullOrEmpty(propertyName))
            {
                Debug.Assert(targetResourceType != null, "targetResourceType != null");
                if (property != null)
                {
                    Debug.Assert(object.ReferenceEquals(targetResourceType.TryResolvePropertyName(propertyName), property), "object.ReferenceEquals(targetResourceType.TryResolvePropertyName(propertyName), property)");
                }
                else
                {
                    Debug.Assert(targetResourceType.IsOpenType, "targetResourceType.IsOpenType");
                }
            }
#endif

            this.propertyName = propertyName;
            this.property = property;
            this.targetResourceType = targetResourceType;
        }
        /// <summary>Applies a property from the reader to the specified resource.</summary>
        /// <param name='property'>The OData property to apply.</param>
        /// <param name='resourceType'>Type of resource.</param>
        /// <param name='resource'>Resource to set value on.</param>
        protected void ApplyProperty(ODataProperty property, ResourceType resourceType, object resource)
        {
            Debug.Assert(property != null, "property != null");
            Debug.Assert(resourceType != null, "resourceType != null");
            Debug.Assert(resource != null, "resource != null");

            string propertyName = property.Name;

            // Note that we include even stream properties in this lookup
            // This is not needed for the purposes of validation, since that has already been done by ODataLib reader.
            ResourceProperty resourceProperty = resourceType.TryResolvePropertyName(propertyName);
            ResourceType propertyResourceType;
            if (resourceProperty == null)
            {
                Debug.Assert(resourceType.IsOpenType, "ODataLib reader should have already failed on undefined properties on non-open types.");
                propertyResourceType = null;
            }
            else if (resourceProperty.Kind == ResourcePropertyKind.Stream)
            {
                // Ignore stream properties in update operations.
                return;
            }
            else
            {
                // Ignore key properties.
                if (this.Update && resourceProperty.IsOfKind(ResourcePropertyKind.Key))
                {
                    return;
                }

                propertyResourceType = resourceProperty.ResourceType;
            }

            object propertyValue = this.ConvertValue(property.Value, ref propertyResourceType);
            if (resourceProperty == null)
            {
                Deserializer.SetOpenPropertyValue(resource, propertyName, propertyValue, this.Service);
            }
            else
            {
                Deserializer.SetPropertyValue(resourceProperty, resource, propertyValue, this.Service);
            }

            return;
        }
        /// <summary>Creates new instance of node representing expanded navigation property.</summary>
        /// <param name="propertyName">The name of the property to project and expand.</param>
        /// <param name="property">The <see cref="ResourceProperty"/> for this property. Can only be null for the root node.</param>
        /// <param name="targetResourceType">Target resource type on which the expansion needs to happen.</param>
        /// <param name="resourceSetWrapper">The resource set to which the expansion leads.</param>
        /// <param name="orderingInfo">The ordering info for this node. null means no ordering to be applied.</param>
        /// <param name="filter">The filter for this node. null means no filter to be applied.</param>
        /// <param name="skipCount">Number of results to skip. null means no results to be skipped.</param>
        /// <param name="takeCount">Maximum number of results to return. null means return all available results.</param>
        /// <param name="maxResultsExpected">Maximum number of expected results. Hint that the provider should return
        /// at least maxResultsExpected + 1 results (if available).</param>
        /// <param name="selectExpandClause">The select expand clause for the current node from the URI Parser.</param>
        internal ExpandedProjectionNode(
            string propertyName,
            ResourceProperty property,
            ResourceType targetResourceType,
            ResourceSetWrapper resourceSetWrapper,
            OrderingInfo orderingInfo,
            Expression filter,
            int? skipCount,
            int? takeCount,
            int? maxResultsExpected,
            SelectExpandClause selectExpandClause)
            : base(propertyName, property, targetResourceType)
        {
            Debug.Assert(resourceSetWrapper != null, "resourceSetWrapper != null");
            Debug.Assert(property != null || (propertyName.Length == 0 && targetResourceType == null), "We don't support open navigation properties.");
            Debug.Assert(property == null || targetResourceType.TryResolvePropertyName(property.Name) != null, "Property must exist on the target resource type");
            Debug.Assert(selectExpandClause != null, "selectExpandClause != null");

            this.resourceSetWrapper = resourceSetWrapper;
            this.orderingInfo = orderingInfo;
            this.filter = filter;
            this.skipCount = skipCount;
            this.takeCount = takeCount;
            this.maxResultsExpected = maxResultsExpected;
            this.nodes = new List<ProjectionNode>();
            this.hasExpandedPropertyOnDerivedType = false;
            this.selectExpandClause = selectExpandClause;
        }
        /// <summary>
        /// Get the list of etag property names given the entity set name and the instance of the resource
        /// </summary>
        /// <param name="containerName">name of the entity set</param>
        /// <param name="resourceType">Type of the resource whose etag properties need to be fetched</param>
        /// <returns>list of etag property names</returns>
        public virtual IList<ResourceProperty> GetETagProperties(string containerName, ResourceType resourceType)
        {
            WebUtil.CheckStringArgumentNullOrEmpty(containerName, "containerName");
            WebUtil.CheckArgumentNull(resourceType, "resourceType");

            EntitySetBase entitySet = this.GetEntitySet(containerName);
            EntityType entityType = this.ObjectContext.MetadataWorkspace.GetItem<EntityType>(resourceType.FullName, DataSpace.CSpace);
            Debug.Assert(entityType != null, "entityType != null");
            List<ResourceProperty> etagProperties = new List<ResourceProperty>();

            // Workspace associated directly with the ObjectContext has metadata only about OSpace, CSpace and OCSpace.
            // Since GetRequiredOriginalValueMembers depends on mapping information (CSSpace metadata),
            // we need to make sure we call this API on a workspace which has information about the CS Mapping.
            // Hence getting workspace from the underlying Entity connection.
            MetadataWorkspace workspace = ((EntityConnection)this.ObjectContext.Connection).GetMetadataWorkspace();
#if EF6Provider
            foreach (EdmMember member in workspace.GetRelevantMembersForUpdate(entitySet, entityType, true /*partialUpdateSupported*/))
#else
            foreach (EdmMember member in workspace.GetRequiredOriginalValueMembers(entitySet, entityType))
#endif
            {
                ResourceProperty property = resourceType.TryResolvePropertyName(member.Name, exceptKind: ResourcePropertyKind.Stream);
                Debug.Assert(property != null, "property != null");
                Debug.Assert(property.ResourceType.ResourceTypeKind == ResourceTypeKind.Primitive, "property.ResourceType.TypeKind == ResourceTypeKind.Primitive");

                // Ignore key properties if they are part of etag, since the uri already has the key information
                // and it makes no sense to duplicate them in etag
                if (!property.IsOfKind(ResourcePropertyKind.Key))
                {
                    etagProperties.Add(property);
                }
            }

            return etagProperties;
        }