/// <summary>
        /// Applies the values of a nested <paramref name="feed"/> to the collection
        /// <paramref name="property"/> of the specified <paramref name="entry"/>.
        /// </summary>
        /// <param name="entry">Entry with collection to be modified.</param>
        /// <param name="property">Collection property on the entry.</param>
        /// <param name="feed">Values to apply onto the collection.</param>
        /// <param name="includeLinks">Whether links that are expanded should be materialized.</param>
        private void ApplyFeedToCollection(
            MaterializerEntry entry,
            ClientPropertyAnnotation property,
            ODataFeed feed,
            bool includeLinks)
        {
            Debug.Assert(entry.Entry != null, "entry != null");
            Debug.Assert(property != null, "property != null");
            Debug.Assert(feed != null, "feed != null");

            ClientEdmModel       edmModel       = this.MaterializerContext.Model;
            ClientTypeAnnotation collectionType = edmModel.GetClientTypeAnnotation(edmModel.GetOrCreateEdmType(property.EntityCollectionItemType));

            IEnumerable <ODataEntry> entries = MaterializerFeed.GetFeed(feed).Entries;

            foreach (ODataEntry feedEntry in entries)
            {
                this.Materialize(MaterializerEntry.GetEntry(feedEntry), collectionType.ElementType, includeLinks);
            }

            ProjectionPlan continuationPlan = includeLinks ?
                                              ODataEntityMaterializer.CreatePlanForDirectMaterialization(property.EntityCollectionItemType) :
                                              ODataEntityMaterializer.CreatePlanForShallowMaterialization(property.EntityCollectionItemType);

            this.ApplyItemsToCollection(
                entry,
                property,
                entries.Select(e => MaterializerEntry.GetEntry(e).ResolvedObject),
                feed.NextPageLink,
                continuationPlan,
                false);
        }
예제 #2
0
            private MaterializerEntry ReadEntryCore()
            {
                MaterializerEntry entry2;

                this.ExpectState(ODataReaderState.EntryStart);
                ODataEntry item = (ODataEntry)this.reader.Item;

                if (item == null)
                {
                    entry2 = MaterializerEntry.CreateEmpty();
                    this.ReadAndExpectState(ODataReaderState.EntryEnd);
                    return(entry2);
                }
                entry2 = MaterializerEntry.CreateEntry(item, this.responseInfo.MaxProtocolVersion);
                do
                {
                    this.AssertRead();
                    switch (this.reader.State)
                    {
                    case ODataReaderState.EntryEnd:
                        break;

                    case ODataReaderState.NavigationLinkStart:
                        entry2.AddNavigationLink(this.ReadNavigationLink());
                        break;

                    default:
                        throw System.Data.Services.Client.Error.InternalError(InternalError.UnexpectedReadState);
                    }
                }while (this.reader.State != ODataReaderState.EntryEnd);
                entry2.UpdateEntityDescriptor();
                return(entry2);
            }
예제 #3
0
        internal static MaterializerEntry ParseSingleEntityPayload(IODataResponseMessage message, ResponseInfo responseInfo, Type expectedType)
        {
            ODataPayloadKind payloadKind = ODataPayloadKind.Entry;

            using (ODataMessageReader reader = ODataMaterializer.CreateODataMessageReader(message, responseInfo, false, ref payloadKind))
            {
                IEdmType               orCreateEdmType = ClientEdmModel.GetModel(responseInfo.MaxProtocolVersion).GetOrCreateEdmType(expectedType);
                ODataReader            reader2         = ODataMaterializer.CreateODataReader(reader, payloadKind, orCreateEdmType, responseInfo.MaxProtocolVersion);
                ODataFeedOrEntryReader reader3         = new ODataFeedOrEntryReader(reader2, responseInfo);
                ODataEntry             currentEntry    = null;
                bool flag = false;
                while (reader3.Read())
                {
                    flag |= reader3.CurrentFeed != null;
                    if (reader3.CurrentEntry != null)
                    {
                        if (currentEntry != null)
                        {
                            throw new InvalidOperationException(System.Data.Services.Client.Strings.AtomParser_SingleEntry_MultipleFound);
                        }
                        currentEntry = reader3.CurrentEntry;
                    }
                }
                if (currentEntry == null)
                {
                    if (flag)
                    {
                        throw new InvalidOperationException(System.Data.Services.Client.Strings.AtomParser_SingleEntry_NoneFound);
                    }
                    throw new InvalidOperationException(System.Data.Services.Client.Strings.AtomParser_SingleEntry_ExpectedFeedOrEntry);
                }
                return(MaterializerEntry.GetEntry(currentEntry));
            }
        }
예제 #4
0
 /// <summary>Projects a simple value from the specified <paramref name="path"/>.</summary>
 /// <param name="materializer">Materializer under which projection is taking place.</param>
 /// <param name="entry">Root entry for paths.</param>
 /// <param name="expectedType">Expected type for <paramref name="entry"/>.</param>
 /// <param name="path">Path to pull value for.</param>
 /// <returns>The value for the specified <paramref name="path"/>.</returns>
 /// <remarks>
 /// This method will not instantiate entity types, except to satisfy requests
 /// for payload-driven feeds or leaf entities.
 /// </remarks>
 internal static object ProjectionValueForPath(object materializer, object entry, Type expectedType, object path)
 {
     Debug.Assert(typeof(ODataEntityMaterializer).IsAssignableFrom(materializer.GetType()), "typeof(ODataEntityMaterializer).IsAssignableFrom(materializer.GetType())");
     Debug.Assert(entry.GetType() == typeof(ODataEntry), "entry.GetType() == typeof(ODataEntry)");
     Debug.Assert(path.GetType() == typeof(ProjectionPath), "path.GetType() == typeof(ProjectionPath)");
     return(((ODataEntityMaterializer)materializer).ProjectionValueForPath(MaterializerEntry.GetEntry((ODataEntry)entry), expectedType, (ProjectionPath)path));
 }
예제 #5
0
 private bool TryReadFeedOrEntry(bool lazy, out ODataFeed feed, out MaterializerEntry entry)
 {
     if (this.TryStartReadFeedOrEntry())
     {
         if (this.reader.State == ODataReaderState.EntryStart)
         {
             entry = this.ReadEntryCore();
             feed  = null;
         }
         else
         {
             entry = null;
             feed  = this.ReadFeedCore(lazy);
         }
     }
     else
     {
         feed  = null;
         entry = null;
     }
     if (feed == null)
     {
         return(entry != null);
     }
     return(true);
 }
예제 #6
0
        /// <summary>Tries to resolve the object as one from the context (only if tracking is enabled).</summary>
        /// <param name="entry">Entry to resolve.</param>
        /// <param name="expectedEntryType">Expected entry type for the specified <paramref name="entry"/>.</param>
        /// <returns>true if the entity was resolved; false otherwise.</returns>
        private bool TryResolveFromContext(MaterializerEntry entry, Type expectedEntryType)
        {
            Debug.Assert(entry.IsAtomOrTracking, "Should not be trying to resolve the entry from the context if entry.IsAtomOrTracking is false.");

            // We should either create a new instance or grab one from the context.
            if (this.MergeOption != MergeOption.NoTracking)
            {
                EntityStates state;
                entry.ResolvedObject = this.EntityTracker.TryGetEntity(entry.Id, out state);
                if (entry.ResolvedObject != null)
                {
                    if (!expectedEntryType.IsInstanceOfType(entry.ResolvedObject))
                    {
                        throw DSClient.Error.InvalidOperation(DSClient.Strings.Deserialize_Current(expectedEntryType, entry.ResolvedObject.GetType()));
                    }

                    ClientEdmModel edmModel = this.Model;
                    entry.ActualType            = edmModel.GetClientTypeAnnotation(edmModel.GetOrCreateEdmType(entry.ResolvedObject.GetType()));
                    entry.EntityHasBeenResolved = true;

                    // Note that deleted items will have their properties overwritten even
                    // if PreserveChanges is used as a merge option.
                    entry.ShouldUpdateFromPayload =
                        this.MergeOption == MergeOption.OverwriteChanges ||
                        (this.MergeOption == MergeOption.PreserveChanges && state == EntityStates.Unchanged) ||
                        (this.MergeOption == MergeOption.PreserveChanges && state == EntityStates.Deleted);

                    this.MaterializationLog.FoundExistingInstance(entry);

                    return(true);
                }
            }

            return(false);
        }
예제 #7
0
 private static void CheckEntryToAccessNotNull(MaterializerEntry entry, string name)
 {
     if (entry.Entry == null)
     {
         throw new NullReferenceException(System.Data.Services.Client.Strings.AtomMaterializer_EntryToAccessIsNull(name));
     }
 }
예제 #8
0
 internal void AddedLink(MaterializerEntry source, string propertyName, object target)
 {
     if (this.Tracking && (ShouldTrackWithContext(source) && ShouldTrackWithContext(target, this.responseInfo.MaxProtocolVersion)))
     {
         LinkDescriptor item = new LinkDescriptor(source.ResolvedObject, propertyName, target, EntityStates.Added);
         this.links.Add(item);
     }
 }
예제 #9
0
 /// <summary>Checks whether the entity on the specified <paramref name="path"/> is null.</summary>
 /// <param name="entry">Root entry for paths.</param>
 /// <param name="expectedType">Expected type for <paramref name="entry"/>.</param>
 /// <param name="path">Path to pull value for.</param>
 /// <returns>Whether the specified <paramref name="path"/> is null.</returns>
 /// <remarks>
 /// This method will not instantiate entity types on the path.
 /// </remarks>
 internal static bool ProjectionCheckValueForPathIsNull(
     object entry,
     Type expectedType,
     object path)
 {
     Debug.Assert(entry.GetType() == typeof(ODataEntry), "entry.GetType() == typeof(ODataEntry)");
     Debug.Assert(path.GetType() == typeof(ProjectionPath), "path.GetType() == typeof(ProjectionPath)");
     return(ODataEntityMaterializer.ProjectionCheckValueForPathIsNull(MaterializerEntry.GetEntry((ODataEntry)entry), expectedType, (ProjectionPath)path));
 }
예제 #10
0
        /// <summary>
        /// Creates the materializer entry.
        /// </summary>
        /// <param name="entry">The entry.</param>
        /// <param name="format">The format the entry was read in.</param>
        /// <param name="isTracking">True if the contents of the entry will be tracked in the context, otherwise False.</param>
        /// <param name="model">The client model.</param>
        /// <returns>A new materializer entry.</returns>
        public static MaterializerEntry CreateEntry(ODataEntry entry, ODataFormat format, bool isTracking, ClientEdmModel model)
        {
            Debug.Assert(entry.GetAnnotation <MaterializerEntry>() == null, "MaterializerEntry has already been created.");

            MaterializerEntry materializerEntry = new MaterializerEntry(entry, format, isTracking, model);

            entry.SetAnnotation <MaterializerEntry>(materializerEntry);

            return(materializerEntry);
        }
예제 #11
0
        internal static ODataEntry ProjectionGetEntry(MaterializerEntry entry, string name)
        {
            MaterializerEntry entry2 = GetPropertyOrThrow(entry.NavigationLinks, name, entry.Id).Entry;

            if (entry2 == null)
            {
                throw new InvalidOperationException(System.Data.Services.Client.Strings.AtomMaterializer_PropertyNotExpectedEntry(name, entry.Id));
            }
            CheckEntryToAccessNotNull(entry2, name);
            return(entry2.Entry);
        }
예제 #12
0
        private void ResolveByCreatingWithType(MaterializerEntry entry, Type type)
        {
            ClientEdmModel model = ClientEdmModel.GetModel(base.ResponseInfo.MaxProtocolVersion);

            entry.ActualType              = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(type));
            entry.ResolvedObject          = Activator.CreateInstance(type);
            entry.CreatedByMaterializer   = true;
            entry.ShouldUpdateFromPayload = true;
            entry.EntityHasBeenResolved   = true;
            this.log.CreatedInstance(entry);
        }
예제 #13
0
 private bool TryReadEntry(out MaterializerEntry entry)
 {
     if (this.TryStartReadFeedOrEntry())
     {
         this.ExpectState(ODataReaderState.EntryStart);
         entry = this.ReadEntryCore();
         return(true);
     }
     entry = null;
     return(false);
 }
예제 #14
0
        /// <summary>
        /// Reads the remainder of an entry.
        /// </summary>
        /// <returns>An entry.</returns>
        private MaterializerEntry ReadEntryCore()
        {
            this.ExpectState(ODataReaderState.EntryStart);

            ODataEntry result = (ODataEntry)this.reader.Item;

            MaterializerEntry          entry;
            List <ODataNavigationLink> navigationLinks = new List <ODataNavigationLink>();

            if (result != null)
            {
                entry = MaterializerEntry.CreateEntry(
                    result,
                    this.readODataFormat,
                    this.mergeOption != MergeOption.NoTracking,
                    this.clientEdmModel);

                do
                {
                    this.AssertRead();

                    switch (this.reader.State)
                    {
                    case ODataReaderState.NavigationLinkStart:
                        // Cache the list of navigation links here but don't add them to the entry because all of the key properties may not be available yet.
                        navigationLinks.Add(this.ReadNavigationLink());
                        break;

                    case ODataReaderState.EntryEnd:
                        break;

                    default:
                        throw DSClient.Error.InternalError(InternalError.UnexpectedReadState);
                    }
                }while (this.reader.State != ODataReaderState.EntryEnd);

                entry.UpdateEntityDescriptor();
            }
            else
            {
                entry = MaterializerEntry.CreateEmpty();
                this.ReadAndExpectState(ODataReaderState.EntryEnd);
            }

            // Add the navigation links here now that all of the property values have been read and are available to build the links.
            foreach (ODataNavigationLink navigationLink in navigationLinks)
            {
                entry.AddNavigationLink(navigationLink);
            }

            return(entry);
        }
예제 #15
0
        private void ApplyFeedToCollection(MaterializerEntry entry, ClientPropertyAnnotation property, ODataFeed feed, bool includeLinks)
        {
            ClientEdmModel           model = ClientEdmModel.GetModel(base.ResponseInfo.MaxProtocolVersion);
            ClientTypeAnnotation     clientTypeAnnotation = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(property.EntityCollectionItemType));
            IEnumerable <ODataEntry> entries = MaterializerFeed.GetFeed(feed).Entries;

            foreach (ODataEntry entry2 in entries)
            {
                this.Materialize(MaterializerEntry.GetEntry(entry2), clientTypeAnnotation.ElementType, includeLinks);
            }
            ProjectionPlan continuationPlan = includeLinks ? CreatePlanForDirectMaterialization(property.EntityCollectionItemType) : CreatePlanForShallowMaterialization(property.EntityCollectionItemType);

            this.ApplyItemsToCollection(entry, property, from e in entries select MaterializerEntry.GetEntry(e).ResolvedObject, feed.NextPageLink, continuationPlan);
        }
예제 #16
0
 private void ResolveOrCreateInstance(MaterializerEntry entry, Type expectedEntryType)
 {
     if (!this.TryResolveAsTarget(entry))
     {
         if (entry.Id == null)
         {
             throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Deserialize_MissingIdElement);
         }
         if (!this.TryResolveAsCreated(entry) && !this.TryResolveFromContext(entry, expectedEntryType))
         {
             this.ResolveByCreating(entry, expectedEntryType);
         }
     }
 }
예제 #17
0
        private bool TryResolveAsTarget(MaterializerEntry entry)
        {
            if (entry.ResolvedObject == null)
            {
                return(false);
            }
            ClientEdmModel model = ClientEdmModel.GetModel(base.ResponseInfo.MaxProtocolVersion);

            entry.ActualType = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(entry.ResolvedObject.GetType()));
            this.log.FoundTargetInstance(entry);
            entry.ShouldUpdateFromPayload = this.mergeOption != MergeOption.PreserveChanges;
            entry.EntityHasBeenResolved   = true;
            return(true);
        }
예제 #18
0
 public static MaterializerEntry CreateEntry(ODataEntry entry, DataServiceProtocolVersion maxProtocolVersion)
 {
     MaterializerEntry annotation = new MaterializerEntry(entry, maxProtocolVersion);
     entry.SetAnnotation<MaterializerEntry>(annotation);
     if (entry.Id == null)
     {
         throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Deserialize_MissingIdElement);
     }
     annotation.EntityDescriptor.Identity = entry.Id;
     annotation.EntityDescriptor.EditLink = entry.EditLink;
     annotation.EntityDescriptor.SelfLink = entry.ReadLink;
     annotation.EntityDescriptor.ETag = entry.ETag;
     return annotation;
 }
예제 #19
0
        private static void MaterializeToList(ODataEntityMaterializer materializer, IEnumerable list, Type nestedExpectedType, IEnumerable <ODataEntry> entries)
        {
            Action <object, object> addToCollectionDelegate = ODataMaterializer.GetAddToCollectionDelegate(list.GetType());

            foreach (ODataEntry entry in entries)
            {
                MaterializerEntry entry2 = MaterializerEntry.GetEntry(entry);
                if (!entry2.EntityHasBeenResolved)
                {
                    materializer.Materialize(entry2, nestedExpectedType, false);
                }
                addToCollectionDelegate(list, entry2.ResolvedObject);
            }
        }
예제 #20
0
        private void ApplyItemsToCollection(MaterializerEntry entry, ClientPropertyAnnotation property, IEnumerable items, Uri nextLink, ProjectionPlan continuationPlan)
        {
            Func <LinkDescriptor, bool> predicate     = null;
            object               instance             = entry.ShouldUpdateFromPayload ? GetOrCreateCollectionProperty(entry.ResolvedObject, property, null) : null;
            ClientEdmModel       model                = ClientEdmModel.GetModel(base.ResponseInfo.MaxProtocolVersion);
            ClientTypeAnnotation clientTypeAnnotation = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(property.EntityCollectionItemType));

            foreach (object obj3 in items)
            {
                if (!clientTypeAnnotation.ElementType.IsAssignableFrom(obj3.GetType()))
                {
                    throw new InvalidOperationException(System.Data.Services.Client.Strings.AtomMaterializer_EntryIntoCollectionMismatch(obj3.GetType().FullName, clientTypeAnnotation.ElementType.FullName));
                }
                if (entry.ShouldUpdateFromPayload)
                {
                    property.SetValue(instance, obj3, property.PropertyName, true);
                    this.log.AddedLink(entry, property.PropertyName, obj3);
                }
            }
            if (entry.ShouldUpdateFromPayload)
            {
                this.FoundNextLinkForCollection(instance as IEnumerable, nextLink, continuationPlan);
            }
            else
            {
                this.FoundNextLinkForUnmodifiedCollection(property.GetValue(entry.ResolvedObject) as IEnumerable);
            }
            if ((this.mergeOption == MergeOption.OverwriteChanges) || (this.mergeOption == MergeOption.PreserveChanges))
            {
                if (predicate == null)
                {
                    predicate = delegate(LinkDescriptor x) {
                        if (MergeOption.OverwriteChanges != this.mergeOption)
                        {
                            return(EntityStates.Added != x.State);
                        }
                        return(true);
                    };
                }
                foreach (object obj4 in (from x in base.ResponseInfo.EntityTracker.GetLinks(entry.ResolvedObject, property.PropertyName).Where <LinkDescriptor>(predicate) select x.Target).Except <object>(EnumerateAsElementType <object>(items)))
                {
                    if (instance != null)
                    {
                        property.RemoveValue(instance, obj4);
                    }
                    this.log.RemovedLink(entry, property.PropertyName, obj4);
                }
            }
        }
예제 #21
0
        public static MaterializerEntry CreateEntry(ODataEntry entry, DataServiceProtocolVersion maxProtocolVersion)
        {
            MaterializerEntry annotation = new MaterializerEntry(entry, maxProtocolVersion);

            entry.SetAnnotation <MaterializerEntry>(annotation);
            if (entry.Id == null)
            {
                throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Deserialize_MissingIdElement);
            }
            annotation.EntityDescriptor.Identity = entry.Id;
            annotation.EntityDescriptor.EditLink = entry.EditLink;
            annotation.EntityDescriptor.SelfLink = entry.ReadLink;
            annotation.EntityDescriptor.ETag     = entry.ETag;
            return(annotation);
        }
예제 #22
0
        private bool TryResolveAsCreated(MaterializerEntry entry)
        {
            MaterializerEntry entry2;

            if (!this.log.TryResolve(entry, out entry2))
            {
                return(false);
            }
            entry.ActualType              = entry2.ActualType;
            entry.ResolvedObject          = entry2.ResolvedObject;
            entry.CreatedByMaterializer   = entry2.CreatedByMaterializer;
            entry.ShouldUpdateFromPayload = entry2.ShouldUpdateFromPayload;
            entry.EntityHasBeenResolved   = true;
            return(true);
        }
예제 #23
0
 protected sealed override bool ReadImplementation()
 {
     base.nextLinkTable.Clear();
     if (!this.ReadNextFeedOrEntry())
     {
         return(false);
     }
     if (((this.CurrentEntry == null) && (this.CurrentFeed != null)) && !this.ReadNextFeedOrEntry())
     {
         return(false);
     }
     MaterializerEntry.GetEntry(this.CurrentEntry).ResolvedObject = this.TargetInstance;
     this.currentValue = this.materializeEntryPlan.Run(this, this.CurrentEntry, base.ExpectedType);
     return(true);
 }
예제 #24
0
 private void MergeLists(MaterializerEntry entry, ClientPropertyAnnotation property, IEnumerable list, Uri nextLink, ProjectionPlan plan)
 {
     if ((entry.ShouldUpdateFromPayload && (property.NullablePropertyType == list.GetType())) && (property.GetValue(entry.ResolvedObject) == null))
     {
         property.SetValue(entry.ResolvedObject, list, property.PropertyName, false);
         this.FoundNextLinkForCollection(list, nextLink, plan);
         foreach (object obj2 in list)
         {
             this.log.AddedLink(entry, property.PropertyName, obj2);
         }
     }
     else
     {
         this.ApplyItemsToCollection(entry, property, list, nextLink, plan);
     }
 }
예제 #25
0
        /// <summary>
        /// Tries to resolve the specified entry as an entry that has already been created in this materialization session or is already in the context.
        /// </summary>
        /// <param name="entry">Entry to resolve.</param>
        /// <param name="expectedEntryType">Expected type of the entry.</param>
        /// <returns>True if the entry was resolved, otherwise False.</returns>
        internal bool TryResolveAsExistingEntry(MaterializerEntry entry, Type expectedEntryType)
        {
            // Resolution is based on the entry Id, so if we can't use that property, we don't even need to try to resolve it.
            if (entry.IsAtomOrTracking)
            {
                // The resolver methods below will both need access to Id, so first ensure it's not null
                if (entry.Id == null)
                {
                    throw DSClient.Error.InvalidOperation(DSClient.Strings.Deserialize_MissingIdElement);
                }

                return(this.TryResolveAsCreated(entry) || this.TryResolveFromContext(entry, expectedEntryType));
            }

            return(false);
        }
        /// <summary>
        /// Populates the collection property on the entry's resolved object with the given items enumerator.
        /// </summary>
        /// <param name="entry">Entry with collection to be modified.</param>
        /// <param name="property">Collection property on the entry.</param>
        /// <param name="items">Values to apply onto the collection.</param>
        /// <param name="nextLink">Next link for collection continuation.</param>
        /// <param name="continuationPlan">Projection plan for collection continuation.</param>
        /// <returns>Collection instance that was populated.</returns>
        private object PopulateCollectionProperty(
            MaterializerEntry entry,
            ClientPropertyAnnotation property,
            IEnumerable <object> items,
            Uri nextLink,
            ProjectionPlan continuationPlan)
        {
            Debug.Assert(entry.Entry != null || entry.ForLoadProperty, "ODataEntry should be non-null except for LoadProperty");
            Debug.Assert(property != null, "property != null");
            Debug.Assert(items != null, "items != null");

            object collection = null;

            ClientEdmModel       edmModel       = this.MaterializerContext.Model;
            ClientTypeAnnotation collectionType = edmModel.GetClientTypeAnnotation(edmModel.GetOrCreateEdmType(property.EntityCollectionItemType));

            if (entry.ShouldUpdateFromPayload)
            {
                collection = this.GetOrCreateCollectionProperty(entry.ResolvedObject, property, entry.ForLoadProperty);

                foreach (object item in items)
                {
                    // Validate that item can be inserted into collection.
                    ValidateCollectionElementTypeIsItemType(item.GetType(), collectionType.ElementType);

                    property.SetValue(collection, item, property.PropertyName, true /* allowAdd? */);

                    this.EntityTrackingAdapter.MaterializationLog.AddedLink(entry, property.PropertyName, item);
                }

                this.FoundNextLinkForCollection(collection as IEnumerable, nextLink, continuationPlan);
            }
            else
            {
                Debug.Assert(!entry.ForLoadProperty, "LoadProperty should always have ShouldUpateForPayload set to true.");

                foreach (object item in items)
                {
                    // Validate that item can be inserted into collection.
                    ValidateCollectionElementTypeIsItemType(item.GetType(), collectionType.ElementType);
                }

                this.FoundNextLinkForUnmodifiedCollection(property.GetValue(entry.ResolvedObject) as IEnumerable);
            }

            return(collection);
        }
        /// <summary>"Resolved" the entity in the <paramref name="entry"/> by instantiating it.</summary>
        /// <param name="entry">Entry to resolve.</param>
        /// <param name="type">Type to create.</param>
        /// <remarks>
        /// After invocation, entry.ResolvedObject is exactly of type <paramref name="type"/>.
        /// </remarks>
        internal void ResolveByCreatingWithType(MaterializerEntry entry, Type type)
        {
            // TODO: CreateNewInstance needs to do all of these operations otherwise an inadvertent call to CreateNewInstance
            // will create a new entity instance that is not tracked in the context or materialization log. Will need to change this
            // prior to shipping if public
            Debug.Assert(
                entry.ResolvedObject == null,
                "entry.ResolvedObject == null -- otherwise we're about to overwrite - should never be called");
            ClientEdmModel edmModel = this.MaterializerContext.Model;

            entry.ActualType              = edmModel.GetClientTypeAnnotation(edmModel.GetOrCreateEdmType(type));
            entry.ResolvedObject          = this.CreateNewInstance(entry.ActualType.EdmTypeReference, type);
            entry.CreatedByMaterializer   = true;
            entry.ShouldUpdateFromPayload = true;
            entry.EntityHasBeenResolved   = true;
            this.EntityTrackingAdapter.MaterializationLog.CreatedInstance(entry);
        }
예제 #28
0
 private static void ApplyLinkProperties(ClientTypeAnnotation actualType, MaterializerEntry entry)
 {
     if (entry.ShouldUpdateFromPayload)
     {
         foreach (ClientPropertyAnnotation annotation in from p in actualType.Properties()
                  where p.PropertyType == typeof(DataServiceStreamLink)
                  select p)
         {
             StreamDescriptor descriptor;
             string           propertyName = annotation.PropertyName;
             if (entry.EntityDescriptor.TryGetNamedStreamInfo(propertyName, out descriptor))
             {
                 annotation.SetValue(entry.ResolvedObject, descriptor.StreamLink, propertyName, true);
             }
         }
     }
 }
예제 #29
0
        /// <summary>Resolved or creates an instance on the specified <paramref name="entry"/>.</summary>
        /// <param name="entry">Entry on which to resolve or create an instance.</param>
        /// <param name="expectedEntryType">Expected type for the <paramref name="entry"/>.</param>
        /// <remarks>
        /// After invocation, the ResolvedObject value of the <paramref name="entry"/>
        /// will be assigned, along with the ActualType value.
        /// </remarks>
        /// <returns>True if an existing entity is found.</returns>
        internal virtual bool TryResolveExistingEntity(MaterializerEntry entry, Type expectedEntryType)
        {
            Debug.Assert(entry.Entry != null, "entry != null");
            Debug.Assert(expectedEntryType != null, "expectedEntryType != null");
            Debug.Assert(entry.EntityHasBeenResolved == false, "entry.EntityHasBeenResolved == false");

            // This will be the case when TargetInstance has been set.
            if (this.TryResolveAsTarget(entry))
            {
                return(true);
            }

            if (this.TryResolveAsExistingEntry(entry, expectedEntryType))
            {
                return(true);
            }

            return(false);
        }
예제 #30
0
        /// <summary>
        /// This method is for parsing CUD operation payloads which should contain
        /// 1 a single entry
        /// 2 An Error
        /// </summary>
        /// <param name="message">the message for the payload</param>
        /// <param name="responseInfo">The current ResponseInfo object</param>
        /// <param name="expectedType">The expected type</param>
        /// <returns>the MaterializerEntry that was read</returns>
        internal static MaterializerEntry ParseSingleEntityPayload(IODataResponseMessage message, ResponseInfo responseInfo, Type expectedType)
        {
            ODataPayloadKind messageType = ODataPayloadKind.Entry;

            using (ODataMessageReader messageReader = CreateODataMessageReader(message, responseInfo, ref messageType))
            {
                IEdmType           edmType = responseInfo.TypeResolver.ResolveExpectedTypeForReading(expectedType);
                ODataReaderWrapper reader  = ODataReaderWrapper.Create(messageReader, messageType, edmType, responseInfo.ResponsePipeline);

                FeedAndEntryMaterializerAdapter parser = new FeedAndEntryMaterializerAdapter(messageReader, reader, responseInfo.Model, responseInfo.MergeOption);

                ODataEntry entry    = null;
                bool       readFeed = false;
                while (parser.Read())
                {
                    readFeed |= parser.CurrentFeed != null;
                    if (parser.CurrentEntry != null)
                    {
                        if (entry != null)
                        {
                            throw new InvalidOperationException(DSClient.Strings.AtomParser_SingleEntry_MultipleFound);
                        }

                        entry = parser.CurrentEntry;
                    }
                }

                if (entry == null)
                {
                    if (readFeed)
                    {
                        throw new InvalidOperationException(DSClient.Strings.AtomParser_SingleEntry_NoneFound);
                    }
                    else
                    {
                        throw new InvalidOperationException(DSClient.Strings.AtomParser_SingleEntry_ExpectedFeedOrEntry);
                    }
                }

                return(MaterializerEntry.GetEntry(entry));
            }
        }
예제 #31
0
        /// <summary>Tries to resolve the object from those created in this materialization session.</summary>
        /// <param name="entry">Entry to resolve.</param>
        /// <returns>true if the entity was resolved; false otherwise.</returns>
        private bool TryResolveAsCreated(MaterializerEntry entry)
        {
            Debug.Assert(entry.IsAtomOrTracking, "Should not be trying to resolve the entry from the current materialization session if entry.IsAtomOrTracking is false.");

            MaterializerEntry existingEntry;

            if (!this.MaterializationLog.TryResolve(entry, out existingEntry))
            {
                return(false);
            }

            Debug.Assert(
                existingEntry.ResolvedObject != null,
                "existingEntry.ResolvedObject != null -- how did it get there otherwise?");
            entry.ActualType              = existingEntry.ActualType;
            entry.ResolvedObject          = existingEntry.ResolvedObject;
            entry.CreatedByMaterializer   = existingEntry.CreatedByMaterializer;
            entry.ShouldUpdateFromPayload = existingEntry.ShouldUpdateFromPayload;
            entry.EntityHasBeenResolved   = true;
            return(true);
        }
예제 #32
0
 private bool TryResolveFromContext(MaterializerEntry entry, Type expectedEntryType)
 {
     if (this.mergeOption != MergeOption.NoTracking)
     {
         EntityStates states;
         entry.ResolvedObject = base.ResponseInfo.EntityTracker.TryGetEntity(entry.Id, out states);
         if (entry.ResolvedObject != null)
         {
             if (!expectedEntryType.IsInstanceOfType(entry.ResolvedObject))
             {
                 throw System.Data.Services.Client.Error.InvalidOperation(System.Data.Services.Client.Strings.Deserialize_Current(expectedEntryType, entry.ResolvedObject.GetType()));
             }
             ClientEdmModel model = ClientEdmModel.GetModel(base.ResponseInfo.MaxProtocolVersion);
             entry.ActualType              = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(entry.ResolvedObject.GetType()));
             entry.EntityHasBeenResolved   = true;
             entry.ShouldUpdateFromPayload = ((this.mergeOption == MergeOption.OverwriteChanges) || ((this.mergeOption == MergeOption.PreserveChanges) && (states == EntityStates.Unchanged))) || ((this.mergeOption == MergeOption.PreserveChanges) && (states == EntityStates.Deleted));
             this.log.FoundExistingInstance(entry);
             return(true);
         }
     }
     return(false);
 }
예제 #33
0
 public static MaterializerNavigationLink CreateLink(ODataNavigationLink link, MaterializerEntry entry)
 {
     MaterializerNavigationLink annotation = new MaterializerNavigationLink(link, entry);
     link.SetAnnotation<MaterializerNavigationLink>(annotation);
     return annotation;
 }
예제 #34
0
 private static bool ShouldTrackWithContext(MaterializerEntry entry)
 {
     return entry.ActualType.IsEntityType;
 }
예제 #35
0
 internal bool TryResolve(MaterializerEntry entry, out MaterializerEntry existingEntry)
 {
     ODataEntry entry2;
     if (this.identityStack.TryGetValue(entry.Id, out entry2))
     {
         existingEntry = MaterializerEntry.GetEntry(entry2);
         return true;
     }
     if (this.appendOnlyEntries.TryGetValue(entry.Id, out entry2))
     {
         EntityStates states;
         this.responseInfo.EntityTracker.TryGetEntity(entry.Id, out states);
         if (states == EntityStates.Unchanged)
         {
             existingEntry = MaterializerEntry.GetEntry(entry2);
             return true;
         }
         this.appendOnlyEntries.Remove(entry.Id);
     }
     existingEntry = null;
     return false;
 }
예제 #36
0
 internal void FoundTargetInstance(MaterializerEntry entry)
 {
     if (ShouldTrackWithContext(entry))
     {
         this.responseInfo.EntityTracker.AttachIdentity(entry.EntityDescriptor, this.mergeOption);
         this.identityStack.Add(entry.Id, entry.Entry);
         this.insertRefreshObject = entry.ResolvedObject;
     }
 }
예제 #37
0
 internal void FoundExistingInstance(MaterializerEntry entry)
 {
     this.identityStack[entry.Id] = entry.Entry;
 }
예제 #38
0
 internal void CreatedInstance(MaterializerEntry entry)
 {
     if (ShouldTrackWithContext(entry))
     {
         this.identityStack.Add(entry.Id, entry.Entry);
         if (this.mergeOption == MergeOption.AppendOnly)
         {
             this.appendOnlyEntries.Add(entry.Id, entry.Entry);
         }
     }
 }
예제 #39
0
 private bool TryReadFeedOrEntry(bool lazy, out ODataFeed feed, out MaterializerEntry entry)
 {
     if (this.TryStartReadFeedOrEntry())
     {
         if (this.reader.State == ODataReaderState.EntryStart)
         {
             entry = this.ReadEntryCore();
             feed = null;
         }
         else
         {
             entry = null;
             feed = this.ReadFeedCore(lazy);
         }
     }
     else
     {
         feed = null;
         entry = null;
     }
     if (feed == null)
     {
         return (entry != null);
     }
     return true;
 }
예제 #40
0
 private bool TryReadEntry(out MaterializerEntry entry)
 {
     if (this.TryStartReadFeedOrEntry())
     {
         this.ExpectState(ODataReaderState.EntryStart);
         entry = this.ReadEntryCore();
         return true;
     }
     entry = null;
     return false;
 }