/// <summary> /// Clones the current link descriptor data /// </summary> /// <param name="clonedSource">The already-cloned source for the link</param> /// <param name="clonedTarget">The already-cloded target for the link</param> /// <returns>A clone of this link descriptor data</returns> public LinkDescriptorData Clone(EntityDescriptorData clonedSource, EntityDescriptorData clonedTarget) { var clone = new LinkDescriptorData(clonedSource, this.SourcePropertyName, clonedTarget); clone.ChangeOrder = this.ChangeOrder; clone.State = this.State; return clone; }
/// <summary> /// Clones the current stream descriptor data /// </summary> /// <param name="clonedEntityDescriptor">The entity descriptor that will contain the result of this clone</param> /// <returns>A clone of the current stream descriptor data</returns> public StreamDescriptorData Clone(EntityDescriptorData clonedEntityDescriptor) { var clone = new StreamDescriptorData(clonedEntityDescriptor, this.Name); clone.State = this.State; clone.ChangeOrder = this.ChangeOrder; clone.ContentType = this.ContentType; clone.ETag = this.ETag; if (this.EditLink != null) { clone.EditLink = new Uri(this.EditLink.OriginalString, UriKind.RelativeOrAbsolute); } if (this.SelfLink != null) { clone.SelfLink = new Uri(this.SelfLink.OriginalString, UriKind.RelativeOrAbsolute); } if (this.SaveStream != null) { clone.SaveStream = this.SaveStream.Clone(); } return(clone); }
/// <summary> /// Initializes a new instance of the <see cref="LinkDescriptorData"/> class. /// </summary> /// <param name="sourceDescriptor">The entity descriptor for the source.</param> /// <param name="sourcePropertyName">Name of the source property.</param> /// <param name="targetDescriptor">The entity descriptor for the target.</param> internal LinkDescriptorData(EntityDescriptorData sourceDescriptor, string sourcePropertyName, EntityDescriptorData targetDescriptor) : base() { this.SourceDescriptor = sourceDescriptor; this.TargetDescriptor = targetDescriptor; this.SourcePropertyName = sourcePropertyName; }
/// <summary> /// Calculates the DataServiceVersion for a particular EntityDescriptor /// </summary> /// <param name="entityDescriptorData">Entity Descriptor Data</param> /// <param name="maxProtocolVersion">The client's max protocol version</param> /// <returns>A Data service protocol version</returns> public DataServiceProtocolVersion CalculateDataServiceVersion(EntityDescriptorData entityDescriptorData, DataServiceProtocolVersion maxProtocolVersion) { ExceptionUtilities.CheckArgumentNotNull(entityDescriptorData, "entityDescriptorData"); Type entityType = entityDescriptorData.Entity.GetType(); EntityType testEntityType = this.entityModelSchema.EntityTypes.Single(et => et.FullName == entityType.FullName); // Calculate expected version based on type's feed mappings. DataServiceProtocolVersion expectedVersion = VersionHelper.CalculateEntityPropertyMappingProtocolVersion(testEntityType, VersionCalculationType.Response, MimeTypes.ApplicationAtomXml, maxProtocolVersion, maxProtocolVersion); // Commenting out this code pending a quick versioning discussion with pratikp and ahmed // Cannot check in as with code it breaks BVT's, want to get this in and update pending discussion 12-7-10 // if (testEntityType.AllProperties.Any(p => p.IsStream())) // { // expectedVersion = VersionHelper.IncreaseVersionIfRequired(expectedVersion, DataServiceProtocolVersion.V4); // } // If there are bag properties then its at least v3 if (testEntityType.HasMultiValue(true) || testEntityType.HasSpatialProperties()) { expectedVersion = VersionHelper.IncreaseVersionIfRequired(expectedVersion, DataServiceProtocolVersion.V4); } return expectedVersion; }
/// <summary> /// Clones the current link descriptor data /// </summary> /// <param name="clonedSource">The already-cloned source for the link</param> /// <param name="clonedTarget">The already-cloded target for the link</param> /// <returns>A clone of this link descriptor data</returns> public LinkDescriptorData Clone(EntityDescriptorData clonedSource, EntityDescriptorData clonedTarget) { var clone = new LinkDescriptorData(clonedSource, this.SourcePropertyName, clonedTarget); clone.ChangeOrder = this.ChangeOrder; clone.State = this.State; return(clone); }
/// <summary> /// Sets the self link. /// </summary> /// <param name="entityDescriptorData">The entity descriptor data.</param> /// <param name="selfLink">The self link.</param> /// <returns><see cref="EntityDescriptorData"/> on which self link has been set.</returns> public static EntityDescriptorData SetSelfLink(this EntityDescriptorData entityDescriptorData, Uri selfLink) { ExceptionUtilities.CheckArgumentNotNull(entityDescriptorData, "entityDescriptorData"); entityDescriptorData.SelfLink = selfLink; return(entityDescriptorData); }
/// <summary> /// Sets the server type name. /// </summary> /// <param name="entityDescriptorData">The entity descriptor data.</param> /// <param name="serverTypeName">The server type name.</param> /// <returns><see cref="EntityDescriptorData"/> on which the server type name has been set.</returns> public static EntityDescriptorData SetServerTypeName(this EntityDescriptorData entityDescriptorData, string serverTypeName) { ExceptionUtilities.CheckArgumentNotNull(entityDescriptorData, "entityDescriptorData"); entityDescriptorData.ServerTypeName = serverTypeName; return(entityDescriptorData); }
/// <summary> /// Sets the entity set name. /// </summary> /// <param name="entityDescriptorData">The entity descriptor data.</param> /// <param name="entitySetName">Name of the entity set.</param> /// <returns><see cref="EntityDescriptorData"/> on which entity set name has been set.</returns> public static EntityDescriptorData SetEntitySetName(this EntityDescriptorData entityDescriptorData, string entitySetName) { ExceptionUtilities.CheckArgumentNotNull(entityDescriptorData, "entityDescriptorData"); entityDescriptorData.EntitySetName = entitySetName; return(entityDescriptorData); }
/// <summary> /// Tries to get entity descriptor data for the specified entity instance. /// </summary> /// <param name="entity">The entity instance for which to return the entity descriptor data.</param> /// <param name="entityData">The entity descriptor data to be retrieved.</param> /// <returns>True if entity descriptor data is found, false otherwise.</returns> /// <exception cref="TaupoArgumentNullException"> /// When entity is null. /// </exception> public bool TryGetEntityDescriptorData(object entity, out EntityDescriptorData entityData) { ExceptionUtilities.CheckArgumentNotNull(entity, "entity"); entityData = this.FindEntityData(entity); return entityData != null; }
/// <summary> /// Sets the identity. /// </summary> /// <param name="entityDescriptorData">The entity descriptor data.</param> /// <param name="identity">The identity.</param> /// <returns><see cref="EntityDescriptorData"/> on which identity has been set.</returns> public static EntityDescriptorData SetIdentity(this EntityDescriptorData entityDescriptorData, Uri identity) { ExceptionUtilities.CheckArgumentNotNull(entityDescriptorData, "entityDescriptorData"); entityDescriptorData.Identity = identity; return(entityDescriptorData); }
/// <summary> /// Sets the ETag. /// </summary> /// <param name="entityDescriptorData">The entity descriptor data.</param> /// <param name="value">The etag for the entity.</param> /// <returns><see cref="EntityDescriptorData"/> on which ETag has been set.</returns> public static EntityDescriptorData SetETag(this EntityDescriptorData entityDescriptorData, string value) { ExceptionUtilities.CheckArgumentNotNull(entityDescriptorData, "entityDescriptorData"); entityDescriptorData.ETag = value; return(entityDescriptorData); }
/// <summary> /// Sets the parent property for insert. /// </summary> /// <param name="entityDescriptorData">The entity descriptor data.</param> /// <param name="parentPropertyForInsert">The parent property for insert.</param> /// <returns><see cref="EntityDescriptorData"/> on which parent property for insert has been set.</returns> public static EntityDescriptorData SetParentPropertyForInsert(this EntityDescriptorData entityDescriptorData, string parentPropertyForInsert) { ExceptionUtilities.CheckArgumentNotNull(entityDescriptorData, "entityDescriptorData"); entityDescriptorData.ParentPropertyForInsert = parentPropertyForInsert; return(entityDescriptorData); }
private static bool IsMatch(EntityDescriptorData entityData, object entityIdentity) { //// entityIdentity could be //// 1. EntityDescriptorData => compare by reference //// 2. Entity instatnce => compare entity by reference //// 3. identity string => compare as strings ExceptionUtilities.Assert(entityData != null, "entityDescriptorData cannot be null!"); return entityData == entityIdentity || entityData.Entity == entityIdentity || (entityData.Identity == (entityIdentity as Uri) && entityData.Identity != null); }
/// <summary> /// Creates an entity descriptor data and puts it into the list of entity descriptors data. /// <see cref="ChangeStateAndChangeOrder"/> for the restrictions on the state and change order. /// </summary> /// <param name="state">The state.</param> /// <param name="changeOrder">The change order.</param> /// <param name="entity">The entity.</param> /// <returns>The created entity descriptor data.</returns> /// <exception cref="TaupoArgumentException"> /// When entity is null. /// </exception> public EntityDescriptorData CreateEntityDescriptorData(EntityStates state, long changeOrder, object entity) { ExceptionUtilities.CheckArgumentNotNull(entity, "entity"); var data = new EntityDescriptorData(this, entity); this.ChangeStateAndChangeOrder(data, state, changeOrder); this.entityDatas.Add(data); return data; }
private bool RemoveEntityData(EntityDescriptorData entityData) { if (!this.entityDatas.Remove(entityData)) { return false; } entityData.RemoveStreamDescriptorDatas(); entityData.RemoveLinkInfoDatas(); SetDetachedState(entityData); return true; }
/// <summary> /// Creates an entity descriptor data and puts it into the list of entity descriptors data. /// <see cref="ChangeStateAndChangeOrder"/> for the restrictions on the state and change order. /// </summary> /// <param name="state">The state.</param> /// <param name="changeOrder">The change order.</param> /// <param name="identity">The identity.</param> /// <param name="entityClrType">The client clr type of the entity.</param> /// <returns>The created entity descriptor data.</returns> /// <exception cref="TaupoArgumentNullException"> /// When entity is null or identity is null. /// </exception> /// <exception cref="TaupoArgumentException"> /// When identity is empty. /// </exception> /// <exception cref="TaupoArgumentException"> /// When state is Added. Use overload that takes entity instance as an input /// as in this case entity instance should always be known. /// </exception> /// <remarks> /// This method is useful when expressing expectations for the LoadProperty method /// as in this case there may be no knowledge about entity instance. /// When entity instance is known use overload that takes entity instance as an input. /// </remarks> public EntityDescriptorData CreateEntityDescriptorData(EntityStates state, long changeOrder, Uri identity, Type entityClrType) { if (state == EntityStates.Added) { throw new TaupoArgumentException("State cannot be Added. Use overload that takes entity as an input argument."); } var data = new EntityDescriptorData(this, identity, entityClrType) .SetIdentity(identity); this.ChangeStateAndChangeOrder(data, state, changeOrder); this.entityDatas.Add(data); return data; }
/// <summary> /// Tracks a pending update to the given descriptor based on values read from a response payload /// </summary> /// <param name="data">The descriptor data to update</param> /// <param name="payload">The payload that was read</param> /// <param name="baseUri">The base uri of the context</param> public void TrackUpdateFromPayload(EntityDescriptorData data, EntityInstance payload, Uri baseUri) { ExceptionUtilities.CheckArgumentNotNull(data, "data"); var update = new PayloadUpdate() { Descriptor = data, Payload = payload, BaseUri = baseUri }; if (!this.IgnoreAllUpdates) { if (this.ApplyUpdatesImmediately) { Apply(update); } else { this.payloadUpdates.Add(update); } } }
/// <summary> /// Clones the current data service context data /// </summary> /// <returns>A clone of the current data service context data</returns> public DataServiceContextData Clone() { var clone = new DataServiceContextData(this.ContextType, this.MaxProtocolVersion); clone.nextChangeOrder = this.nextChangeOrder; if (this.BaseUri != null) { clone.BaseUri = new Uri(this.BaseUri.OriginalString, UriKind.RelativeOrAbsolute); } clone.AddAndUpdateResponsePreference = this.AddAndUpdateResponsePreference; clone.MergeOption = this.MergeOption; clone.ResolveEntitySet = this.ResolveEntitySet; clone.ResolveName = this.ResolveName; clone.ResolveType = this.ResolveType; clone.UsePostTunneling = this.UsePostTunneling; clone.HttpStack = this.HttpStack; var mapping = new Dictionary<EntityDescriptorData, EntityDescriptorData>(ReferenceEqualityComparer.Create<EntityDescriptorData>()); foreach (var entityDescriptor in this.entityDatas) { var clonedDescriptor = entityDescriptor.Clone(clone); mapping[entityDescriptor] = clonedDescriptor; clone.entityDatas.Add(clonedDescriptor); } foreach (var linkDescriptor in this.linkDatas) { EntityDescriptorData clonedSource = null; EntityDescriptorData clonedTarget = null; mapping.TryGetValue(linkDescriptor.SourceDescriptor, out clonedSource); if (linkDescriptor.TargetDescriptor != null) { mapping.TryGetValue(linkDescriptor.TargetDescriptor, out clonedTarget); } var clonedDescriptor = linkDescriptor.Clone(clonedSource, clonedTarget); clone.linkDatas.Add(clonedDescriptor); } return clone; }
/// <summary> /// Clones the current entity descriptor data /// </summary> /// <returns>A clone of the current entity descriptor data</returns> /// <param name="clonedContextData">The cloned context data which will contain the cloned entity descriptor data</param> public EntityDescriptorData Clone(DataServiceContextData clonedContextData) { var clone = new EntityDescriptorData(clonedContextData); clone.ChangeOrder = this.ChangeOrder; clone.entity = this.entity; clone.EntityClrType = this.EntityClrType; clone.EntitySetName = this.EntitySetName; clone.ETag = this.ETag; clone.Identity = this.Identity; clone.linkInfos.AddRange(this.linkInfos.Select(l => l.Clone())); clone.operationDescriptors.AddRange(this.operationDescriptors.Select(o => o.Clone())); clone.streamDescriptors.AddRange(this.streamDescriptors.Select(n => n.Clone(clone))); clone.ParentForInsert = this.ParentForInsert; clone.ParentPropertyForInsert = this.ParentPropertyForInsert; clone.State = this.State; if (this.EditLink != null) { clone.EditLink = new Uri(this.EditLink.OriginalString, UriKind.RelativeOrAbsolute); } if (this.SelfLink != null) { clone.SelfLink = new Uri(this.SelfLink.OriginalString, UriKind.RelativeOrAbsolute); } if (this.InsertLink != null) { clone.InsertLink = new Uri(this.InsertLink.OriginalString, UriKind.RelativeOrAbsolute); } if (this.IsMediaLinkEntry) { clone.defaultStreamDescriptor = this.defaultStreamDescriptor.Clone(clone); } return(clone); }
/// <summary> /// Updates the entity decriptor data with values from response headers /// </summary> /// <param name="entityDescriptorData">The descriptor data to update</param> /// <param name="headers">The response headers</param> public static void UpdateFromHeaders(this EntityDescriptorData entityDescriptorData, IDictionary <string, string> headers) { ExceptionUtilities.CheckArgumentNotNull(entityDescriptorData, "entityDescriptorData"); ExceptionUtilities.CheckArgumentNotNull(headers, "headers"); string etag; headers.TryGetValue(HttpHeaders.ETag, out etag); entityDescriptorData.SetETag(etag); // we do want to set null if the header is not present string location; if (headers.TryGetValue(HttpHeaders.Location, out location)) { entityDescriptorData.SetEditLink(new Uri(location)); } string dataServiceId; if (headers.TryGetValue(HttpHeaders.DataServiceId, out dataServiceId)) { entityDescriptorData.SetIdentity(new Uri(dataServiceId, UriKind.RelativeOrAbsolute)); } }
/// <summary> /// Creates the link descriptor data and puts in into the list of link descriptors data. /// <see cref="ChangeStateAndChangeOrder"/> for the restrictions on the state and change order. /// </summary> /// <param name="state">The state.</param> /// <param name="changeOrder">The change order.</param> /// <param name="source">The source.</param> /// <param name="sourcePropertyName">Name of the source property.</param> /// <param name="target">The target.</param> /// <returns>The created link descriptor data.</returns> /// <exception cref="TaupoArgumentNullException"> /// When source or sourcePropertyName is null. /// </exception> /// <exception cref="TaupoArgumentException"> /// When sourcePropertyName is empty. /// </exception> /// <exception cref="TaupoInvalidOperationException"> /// When entity descriptor data is not found for the source or target (if target is not null). /// </exception> public LinkDescriptorData CreateLinkDescriptorData(EntityStates state, long changeOrder, object source, string sourcePropertyName, object target) { CheckLinkArguments(source, sourcePropertyName); EntityDescriptorData sourceData = this.FindEntityData(source); if (sourceData == null) { throw new TaupoInvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Could not find entity descriptor data for the source: {0}.", source)); } // Target can be null EntityDescriptorData targetData = null; if (target != null) { targetData = this.FindEntityData(target); if (targetData == null) { throw new TaupoInvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Could not find entity descriptor data for the target: {0}.", target)); } } return this.CreateLinkDescriptorData(state, changeOrder, sourceData, sourcePropertyName, targetData); }
/// <summary> /// Initializes a new instance of the <see cref="StreamDescriptorData"/> class. /// </summary> /// <param name="entityDescriptorData">The entity descriptor data containing the stream</param> internal StreamDescriptorData(EntityDescriptorData entityDescriptorData) { ExceptionUtilities.CheckArgumentNotNull(entityDescriptorData, "entityDescriptorData"); this.EntityDescriptor = entityDescriptorData; }
/// <summary> /// Normalizes the given entity payload element /// </summary> /// <param name="entityPayload">The entity payload element</param> /// <param name="entityDescriptorData">The descriptor data for the entity</param> public void Normalize(EntityInstance entityPayload, EntityDescriptorData entityDescriptorData) { ExceptionUtilities.CheckArgumentNotNull(entityPayload, "entityPayload"); ExceptionUtilities.CheckArgumentNotNull(entityDescriptorData, "entityDescriptorData"); this.typeStack.Push(entityDescriptorData.EntityClrType); // do this before recursing because it could be over-written by the visit method entityPayload.FullTypeName = entityDescriptorData.ServerTypeName; entityPayload.Id = string.Empty; if (entityDescriptorData.Identity != null) { entityPayload.Id = entityDescriptorData.Identity.OriginalString; } entityPayload.Accept(this); }
private EntityInstance BuildEntityPayload( DataServiceContextData contextData, IDictionary<object, IEnumerable<NamedValue>> propertyValuesBeforeSave, EntityDescriptorData entityDescriptorData, DataServiceProtocolVersion dsv) { IEnumerable<NamedValue> propertyValues; ExceptionUtilities.Assert(propertyValuesBeforeSave.TryGetValue(entityDescriptorData.Entity, out propertyValues), "Could not find property values for descriptor: {0}", entityDescriptorData); var entityType = this.ModelSchema.EntityTypes.Single(t => t.FullName == entityDescriptorData.EntityClrType.FullName); var entityInstance = this.PayloadBuilder.EntityInstance(entityType, propertyValues); new ExpectedPayloadNormalizer(contextData, dsv).Normalize(entityInstance, entityDescriptorData); return entityInstance; }
private ExpectedClientRequest CreateEntityUpdateRequest(DataServiceContextData contextData, IDictionary<object, IEnumerable<NamedValue>> propertyValuesBeforeSave, EntityDescriptorData entityDescriptorData, SaveChangesOptions options) { var request = new ExpectedClientRequest() { Verb = GetUpdateVerb(options), Uri = entityDescriptorData.EditLink, }; string preference = contextData.AddAndUpdateResponsePreference.ToHeaderValue(); var dsv = GetDataServiceVersion(request.Verb, preference); dsv = dsv.IncreaseVersionIfRequired(this.VersionCalculator.CalculateDataServiceVersion(entityDescriptorData, contextData.MaxProtocolVersion)); request.Headers[HttpHeaders.DataServiceVersion] = ToClientHeaderFormat(dsv); request.Headers[HttpHeaders.IfMatch] = entityDescriptorData.ETag; request.Headers[HttpHeaders.Prefer] = preference; this.SetDefaultAcceptHeader(request, options); this.SetContentTypeHeaderForEntity(request); request.Body = this.BuildEntityPayload(contextData, propertyValuesBeforeSave, entityDescriptorData, dsv); string hintString = @"Entity update\r\n{{\r\n Descriptor = {0}\r\n Options = {1}\r\n}}"; request.DebugHintString = string.Format(CultureInfo.InvariantCulture, hintString, entityDescriptorData, options); return request; }
private ExpectedClientRequest CreateEntityDeleteRequest(EntityDescriptorData entityDescriptorData, SaveChangesOptions options) { var request = new ExpectedClientRequest() { Verb = HttpVerb.Delete, Uri = entityDescriptorData.EditLink, }; request.Headers[HttpHeaders.IfMatch] = entityDescriptorData.ETag; request.Headers[HttpHeaders.Prefer] = null; request.Headers[HttpHeaders.DataServiceVersion] = ToClientHeaderFormat(DataServiceProtocolVersion.V4); this.SetDefaultAcceptHeader(request, options); request.Headers[HttpHeaders.ContentType] = null; string hintString = @"Entity delete\r\n{{\r\n Descriptor = {0}\r\n}}"; request.DebugHintString = string.Format(CultureInfo.InvariantCulture, hintString, entityDescriptorData); return request; }
/// <summary> /// Creates EntityChangeData which captures the state of the specified entity descriptor data. /// </summary> /// <param name="entityDescriptorData">The entity descriptor data.</param> /// <param name="propertiesValues">The properties values before SaveChanges.</param> /// <returns>Entity change data.</returns> public static ChangeData Create(EntityDescriptorData entityDescriptorData, IEnumerable<NamedValue> propertiesValues) { EntityChangeData changeData = new EntityChangeData(entityDescriptorData); foreach (NamedValue nv in propertiesValues) { changeData.CachedPropertiesValues.Add(nv.Name, nv.Value); } changeData.ClrTypeForRequery = entityDescriptorData.EntityClrType; return changeData; }
/// <summary> /// Applies all pending updates for the given entity descriptor data /// </summary> /// <param name="data">The descriptor data to update</param> public void ApplyPendingUpdates(EntityDescriptorData data) { foreach (var update in this.headerUpdates.Where(u => u.Descriptor == data).ToList()) { ExceptionUtilities.Assert(!this.ApplyUpdatesImmediately, "Should not have any pending header updates when ApplyUpdatesImmediately is true"); Apply(update); this.headerUpdates.Remove(update); } foreach (var update in this.payloadUpdates.Where(u => u.Descriptor == data).ToList()) { ExceptionUtilities.Assert(!this.ApplyUpdatesImmediately, "Should not have any pending payload updates when ApplyUpdatesImmediately is true"); Apply(update); this.payloadUpdates.Remove(update); } }
/// <summary> /// Creates the link descriptor data and puts in into the list of link descriptors data. /// <see cref="ChangeStateAndChangeOrder"/> for the restrictions on the state and change order. /// </summary> /// <param name="state">The state.</param> /// <param name="changeOrder">The change order.</param> /// <param name="sourceData">The source.</param> /// <param name="sourcePropertyName">Name of the source property.</param> /// <param name="targetData">The target.</param> /// <returns>The created link descriptor data.</returns> /// <exception cref="TaupoArgumentNullException"> /// When source or sourcePropertyName is null. /// </exception> /// <exception cref="TaupoArgumentException"> /// When sourcePropertyName is empty. /// </exception> /// <exception cref="TaupoInvalidOperationException"> /// When entity descriptor data is not found for the source or target (if target is not null). /// </exception> public LinkDescriptorData CreateLinkDescriptorData(EntityStates state, long changeOrder, EntityDescriptorData sourceData, string sourcePropertyName, EntityDescriptorData targetData) { ExceptionUtilities.CheckArgumentNotNull(sourceData, "sourceData"); ExceptionUtilities.CheckArgumentNotNull(sourcePropertyName, "sourcePropertyName"); var linkData = new LinkDescriptorData(sourceData, sourcePropertyName, targetData); this.ChangeStateAndChangeOrder(linkData, state, changeOrder); this.linkDatas.Add(linkData); return linkData; }
/// <summary> /// Clones the current stream descriptor data /// </summary> /// <param name="clonedEntityDescriptor">The entity descriptor that will contain the result of this clone</param> /// <returns>A clone of the current stream descriptor data</returns> public StreamDescriptorData Clone(EntityDescriptorData clonedEntityDescriptor) { var clone = new StreamDescriptorData(clonedEntityDescriptor, this.Name); clone.State = this.State; clone.ChangeOrder = this.ChangeOrder; clone.ContentType = this.ContentType; clone.ETag = this.ETag; if (this.EditLink != null) { clone.EditLink = new Uri(this.EditLink.OriginalString, UriKind.RelativeOrAbsolute); } if (this.SelfLink != null) { clone.SelfLink = new Uri(this.SelfLink.OriginalString, UriKind.RelativeOrAbsolute); } if (this.SaveStream != null) { clone.SaveStream = this.SaveStream.Clone(); } return clone; }
/// <summary> /// Tracks a pending update to the given descriptor based on values read from response headers /// </summary> /// <param name="data">The descriptor data to update</param> /// <param name="headers">The headers that were read</param> public void TrackUpdateFromHeaders(EntityDescriptorData data, IDictionary<string, string> headers) { ExceptionUtilities.CheckArgumentNotNull(data, "data"); var update = new HeaderUpdate() { Descriptor = data, Headers = headers }; if (!this.IgnoreAllUpdates) { if (this.ApplyUpdatesImmediately) { Apply(update); } else { this.headerUpdates.Add(update); } } }
/// <summary> /// Initializes a new instance of the <see cref="StreamDescriptorData"/> class. /// </summary> /// <param name="entityDescriptorData">The entity descriptor data containing the stream</param> /// <param name="name">The name of the stream</param> internal StreamDescriptorData(EntityDescriptorData entityDescriptorData, string name) : this(entityDescriptorData) { this.Name = name; }
/// <summary> /// Extension method to either find or create a link descriptor with the given values /// </summary> /// <param name="contextData">The context data</param> /// <param name="sourceDescriptor">The source descriptor</param> /// <param name="propertyName">The property name</param> /// <param name="targetDescriptor">The target descriptor</param> /// <returns>A link descriptor with the given values</returns> public static LinkDescriptorData MaterializeLinkDescriptor(this DataServiceContextData contextData, EntityDescriptorData sourceDescriptor, string propertyName, EntityDescriptorData targetDescriptor) { var existingLink = contextData.LinkDescriptorsData.SingleOrDefault(l => l.SourceDescriptor == sourceDescriptor && l.SourcePropertyName == propertyName && l.TargetDescriptor == targetDescriptor); if (existingLink == null) { existingLink = contextData.CreateLinkDescriptorData(EntityStates.Unchanged, 0, sourceDescriptor, propertyName, targetDescriptor); } return existingLink; }
/// <summary> /// Clones the current entity descriptor data /// </summary> /// <returns>A clone of the current entity descriptor data</returns> /// <param name="clonedContextData">The cloned context data which will contain the cloned entity descriptor data</param> public EntityDescriptorData Clone(DataServiceContextData clonedContextData) { var clone = new EntityDescriptorData(clonedContextData); clone.ChangeOrder = this.ChangeOrder; clone.entity = this.entity; clone.EntityClrType = this.EntityClrType; clone.EntitySetName = this.EntitySetName; clone.ETag = this.ETag; clone.Identity = this.Identity; clone.linkInfos.AddRange(this.linkInfos.Select(l => l.Clone())); clone.operationDescriptors.AddRange(this.operationDescriptors.Select(o => o.Clone())); clone.streamDescriptors.AddRange(this.streamDescriptors.Select(n => n.Clone(clone))); clone.ParentForInsert = this.ParentForInsert; clone.ParentPropertyForInsert = this.ParentPropertyForInsert; clone.State = this.State; if (this.EditLink != null) { clone.EditLink = new Uri(this.EditLink.OriginalString, UriKind.RelativeOrAbsolute); } if (this.SelfLink != null) { clone.SelfLink = new Uri(this.SelfLink.OriginalString, UriKind.RelativeOrAbsolute); } if (this.InsertLink != null) { clone.InsertLink = new Uri(this.InsertLink.OriginalString, UriKind.RelativeOrAbsolute); } if (this.IsMediaLinkEntry) { clone.defaultStreamDescriptor = this.defaultStreamDescriptor.Clone(clone); } return clone; }
/// <summary> /// Updates the stream decriptor data with values from a response payload /// </summary> /// <param name="entityDescriptorData">The descriptor data to update</param> /// <param name="entityData">A representation of the payload</param> /// <param name="contextBaseUri">The base uri of the context</param> public static void UpdateFromPayload(this EntityDescriptorData entityDescriptorData, EntityInstance entityData, Uri contextBaseUri) { ExceptionUtilities.CheckArgumentNotNull(entityDescriptorData, "entityDescriptorData"); ExceptionUtilities.CheckArgumentNotNull(entityData, "entityData"); var xmlBase = entityData.Annotations.OfType <XmlBaseAnnotation>().SingleOrDefault(); entityDescriptorData.SetIdentity(GetAbsoluteUriForLink(contextBaseUri, xmlBase, entityData.Id)); entityDescriptorData.SetETag(entityData.ETag); entityDescriptorData.SetServerTypeName(entityData.FullTypeName); var editLink = entityData.EditLink; if (editLink != null) { entityDescriptorData.SetEditLink(GetAbsoluteUriForLink(contextBaseUri, xmlBase, editLink)); } var selfLink = entityData.Annotations.OfType <SelfLinkAnnotation>().SingleOrDefault(); if (selfLink != null) { entityDescriptorData.SetSelfLink(GetAbsoluteUriForLink(contextBaseUri, xmlBase, selfLink.Value)); } foreach (var navigation in entityData.Properties.OfType <NavigationPropertyInstance>()) { var linkInfoData = entityDescriptorData.LinkInfos.SingleOrDefault(l => l.Name == navigation.Name); if (linkInfoData == null) { linkInfoData = entityDescriptorData.CreateLinkInfoData(navigation.Name); } if (navigation.AssociationLink != null) { linkInfoData.RelationshipLink = GetAbsoluteUriForLink(contextBaseUri, xmlBase, navigation.AssociationLink.UriString); } string navigationLink = null; if (navigation.Value != null) { if (navigation.IsExpanded) { navigationLink = ((ExpandedLink)navigation.Value).UriString; } else { navigationLink = ((DeferredLink)navigation.Value).UriString; } } if (navigationLink != null) { linkInfoData.NavigationLink = GetAbsoluteUriForLink(contextBaseUri, xmlBase, navigationLink); } } entityDescriptorData.RemoveOperationDescriptorData(); foreach (var operation in entityData.ServiceOperationDescriptors) { entityDescriptorData.CreateOperationDescriptorData( new Uri(operation.Metadata, UriKind.RelativeOrAbsolute), new Uri(operation.Target, UriKind.RelativeOrAbsolute), operation.Title, operation.IsAction); } if (entityData.IsMediaLinkEntry()) { if (entityData.StreamSourceLink != null) { entityDescriptorData.ReadStreamUri = GetAbsoluteUriForLink(contextBaseUri, xmlBase, entityData.StreamSourceLink); } if (entityData.StreamEditLink != null) { entityDescriptorData.EditStreamUri = GetAbsoluteUriForLink(contextBaseUri, xmlBase, entityData.StreamEditLink); } entityDescriptorData.StreamETag = entityData.StreamETag; } foreach (var namedStream in entityData.Properties.OfType <NamedStreamInstance>()) { var streamDescriptor = entityDescriptorData.StreamDescriptors.SingleOrDefault(n => n.Name == namedStream.Name); if (streamDescriptor == null) { streamDescriptor = entityDescriptorData.CreateStreamDescriptorData(EntityStates.Unchanged, 0, namedStream.Name); } // apply self link's content type first, as the value from the edit link should 'win' if (namedStream.SourceLink != null) { streamDescriptor.SelfLink = GetAbsoluteUriForLink(contextBaseUri, xmlBase, namedStream.SourceLink); streamDescriptor.ContentType = namedStream.SourceLinkContentType; } if (namedStream.EditLink != null) { streamDescriptor.EditLink = GetAbsoluteUriForLink(contextBaseUri, xmlBase, namedStream.EditLink); streamDescriptor.ContentType = namedStream.EditLinkContentType; } streamDescriptor.ETag = namedStream.ETag; } // TODO: update property values from payload }
internal static Uri GetEntityInsertUri(DataServiceContextData contextData, EntityDescriptorData entityDescriptorData) { Uri insertUri; if (entityDescriptorData.InsertLink != null) { insertUri = entityDescriptorData.InsertLink; } else { ExceptionUtilities.CheckObjectNotNull(entityDescriptorData.ParentForInsert, "Entity descriptor data did not have insert link or parent for insert: {0}", entityDescriptorData); ExceptionUtilities.CheckObjectNotNull(entityDescriptorData.ParentPropertyForInsert, "Entity descriptor data did not have insert link or parent property for insert: {0}", entityDescriptorData); var parentDescriptor = contextData.GetEntityDescriptorData(entityDescriptorData.ParentForInsert); var linkInfo = parentDescriptor.LinkInfos.SingleOrDefault(l => l.Name == entityDescriptorData.ParentPropertyForInsert); if (linkInfo != null && linkInfo.NavigationLink != null) { insertUri = linkInfo.NavigationLink; } else { insertUri = new Uri(UriHelpers.ConcatenateUriSegments(parentDescriptor.EditLink.OriginalString, entityDescriptorData.ParentPropertyForInsert), UriKind.RelativeOrAbsolute); if (!insertUri.IsAbsoluteUri && contextData.BaseUri != null) { insertUri = new Uri(contextData.BaseUri, insertUri); } } } return insertUri; }
/// <summary> /// Extension method to either find or create a link descriptor with the given values /// </summary> /// <param name="contextData">The context data</param> /// <param name="sourceDescriptor">The source descriptor</param> /// <param name="propertyName">The property name</param> /// <param name="targetDescriptor">The target descriptor</param> /// <returns>A link descriptor with the given values</returns> public static LinkDescriptorData MaterializeLinkDescriptor(this DataServiceContextData contextData, EntityDescriptorData sourceDescriptor, string propertyName, EntityDescriptorData targetDescriptor) { var existingLink = contextData.LinkDescriptorsData.SingleOrDefault(l => l.SourceDescriptor == sourceDescriptor && l.SourcePropertyName == propertyName && l.TargetDescriptor == targetDescriptor); if (existingLink == null) { existingLink = contextData.CreateLinkDescriptorData(EntityStates.Unchanged, 0, sourceDescriptor, propertyName, targetDescriptor); } return(existingLink); }
private ExpectedClientRequest CreateEntityInsertRequest(DataServiceContextData contextData, IDictionary<object, IEnumerable<NamedValue>> propertyValuesBeforeSave, EntityDescriptorData entityDescriptorData, SaveChangesOptions options) { ExceptionUtilities.Assert(!entityDescriptorData.IsMediaLinkEntry, "Can only be used for non media-link-entries"); var insertUri = GetEntityInsertUri(contextData, entityDescriptorData); ExpectedClientRequest request = new ExpectedClientRequest() { Verb = HttpVerb.Post, Uri = insertUri }; string preference = contextData.AddAndUpdateResponsePreference.ToHeaderValue(); DataServiceProtocolVersion dsv = GetDataServiceVersion(HttpVerb.Post, preference); dsv = dsv.IncreaseVersionIfRequired(this.VersionCalculator.CalculateDataServiceVersion(entityDescriptorData, contextData.MaxProtocolVersion)); var payload = this.BuildEntityPayload(contextData, propertyValuesBeforeSave, entityDescriptorData, dsv); request.Body = payload; this.AddFoldedLinksToEntityInsertPayload(contextData, entityDescriptorData, payload); request.Headers[HttpHeaders.DataServiceVersion] = ToClientHeaderFormat(dsv); request.Headers[HttpHeaders.IfMatch] = null; request.Headers[HttpHeaders.Prefer] = preference; this.SetDefaultAcceptHeader(request, options); this.SetContentTypeHeaderForEntity(request); string hintString = @"Entity insert\r\n{{\r\n Descriptor = {0}\r\n Options = {1}\r\n}}"; request.DebugHintString = string.Format(CultureInfo.InvariantCulture, hintString, entityDescriptorData, options); return request; }
private void AddFoldedLinksToEntityInsertPayload(DataServiceContextData contextData, EntityDescriptorData entityDescriptorData, EntityInstance payload) { var entityType = this.ModelSchema.EntityTypes.Single(t => t.FullName == entityDescriptorData.EntityClrType.FullName); foreach (var linkDescriptor in contextData.LinkDescriptorsData.Where(l => l.SourceDescriptor == entityDescriptorData)) { if (linkDescriptor.TargetDescriptor.State == EntityStates.Added) { continue; } var navigationProperty = entityType.AllNavigationProperties.Single(n => n.Name == linkDescriptor.SourcePropertyName); string contentType = MimeTypes.ApplicationAtomXml + ";type="; if (navigationProperty.ToAssociationEnd.Multiplicity == EndMultiplicity.Many) { contentType += "feed"; } else { contentType += "entry"; } // note: the edit-link is used rather than identity because the server needs to be able to query for the target entity // and the identity may not be an actual uri var link = new DeferredLink() { UriString = linkDescriptor.TargetDescriptor.EditLink.OriginalString } .WithContentType(contentType).WithTitleAttribute(linkDescriptor.SourcePropertyName); payload.Add(new NavigationPropertyInstance(linkDescriptor.SourcePropertyName, link)); } }
/// <summary> /// Initializes a new instance of the <see cref="EntityChangeData"/> class. /// </summary> /// <param name="entityDescriptorData">The entity descriptor data.</param> protected EntityChangeData(EntityDescriptorData entityDescriptorData) : base(entityDescriptorData) { this.CachedPropertiesValues = new Dictionary<string, object>(); }