示例#1
0
        /// <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,
            ODataResourceSet 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.ResourceSetItemType));

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

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

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

            this.ApplyItemsToCollection(
                entry,
                property,
                entries.Select(e => MaterializerEntry.GetEntry(e).ResolvedObject),
                feed.NextPageLink,
                continuationPlan,
                false);
        }
示例#2
0
        /// <summary>Runs this plan.</summary>
        /// <param name="materializer">Materializer under which materialization should happen.</param>
        /// <param name="entry">Root entry to materialize.</param>
        /// <param name="expectedType">Expected type for the <paramref name="entry"/>.</param>
        /// <returns>The materialized object.</returns>
        internal object Run(ODataEntityMaterializer materializer, ODataResource entry, Type expectedType)
        {
            Debug.Assert(materializer != null, "materializer != null");
            Debug.Assert(entry != null, "entry != null");

            return(this.Plan(materializer, entry, expectedType));
        }
示例#3
0
        /// <summary>Runs this plan.</summary>
        /// <param name="materializer">Materializer under which materialization should happen.</param>
        /// <param name="entry">Root entry to materialize.</param>
        /// <param name="expectedType">Expected type for the <paramref name="entry"/>.</param>
        /// <returns>The materialized object.</returns>
        internal object Run(ODataEntityMaterializer materializer, ODataEntry entry, Type expectedType)
        {
            Debug.Assert(materializer != null, "materializer != null");
            Debug.Assert(entry != null, "entry != null");

            return this.Plan(materializer, entry, expectedType);
        }
 /// <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));
 }
 /// <summary>Initializes a projection-driven entry (with a specific type and specific properties).</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="resultType">Expected result type.</param>
 /// <param name="properties">Properties to materialize.</param>
 /// <param name="propertyValues">Functions to get values for functions.</param>
 /// <returns>The initialized entry.</returns>
 internal static object ProjectionInitializeEntity(
     object materializer,
     object entry,
     Type expectedType,
     Type resultType,
     string[] properties,
     Func <object, object, Type, object>[] propertyValues)
 {
     Debug.Assert(typeof(ODataEntityMaterializer).IsAssignableFrom(materializer.GetType()), "typeof(ODataEntityMaterializer).IsAssignableFrom(materializer.GetType())");
     Debug.Assert(entry.GetType() == typeof(ODataEntry), "entry.GetType() == typeof(ODataEntry)");
     return(ODataEntityMaterializer.ProjectionInitializeEntity((ODataEntityMaterializer)materializer, MaterializerEntry.GetEntry((ODataEntry)entry), expectedType, resultType, properties, propertyValues));
 }
 /// <summary>Provides support for Select invocations for projections.</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="resultType">Expected result type.</param>
 /// <param name="path">Path to traverse.</param>
 /// <param name="selector">Selector callback.</param>
 /// <returns>An enumerable with the select results.</returns>
 internal static IEnumerable ProjectionSelect(
     object materializer,
     object entry,
     Type expectedType,
     Type resultType,
     object path,
     Func <object, object, Type, object> selector)
 {
     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.ProjectionSelect((ODataEntityMaterializer)materializer, MaterializerEntry.GetEntry((ODataEntry)entry), expectedType, resultType, (ProjectionPath)path, selector));
 }
 /// <summary>Provides support for getting payload entries during projections.</summary>
 /// <param name="entry">Entry to get sub-entry from.</param>
 /// <param name="name">Name of sub-entry.</param>
 /// <returns>The sub-entry (never null).</returns>
 internal static object ProjectionGetEntry(object entry, string name)
 {
     Debug.Assert(entry.GetType() == typeof(ODataEntry), "entry.GetType() == typeof(ODataEntry)");
     return(ODataEntityMaterializer.ProjectionGetEntry(MaterializerEntry.GetEntry((ODataEntry)entry), name));
 }
 /// <summary>Creates a list to a target element type.</summary>
 /// <param name="materializer">Materializer used to flow link tracking.</param>
 /// <typeparam name="T">Element type to enumerate over.</typeparam>
 /// <typeparam name="TTarget">Element type for list.</typeparam>
 /// <param name="source">Element source.</param>
 /// <returns>
 /// An IEnumerable&lt;T&gt; that iterates over the specified <paramref name="source"/>.
 /// </returns>
 /// <remarks>
 /// This method should be unnecessary with .NET 4.0 covariance support.
 /// </remarks>
 internal static List <TTarget> ListAsElementType <T, TTarget>(object materializer, IEnumerable <T> source) where T : TTarget
 {
     Debug.Assert(typeof(ODataEntityMaterializer).IsAssignableFrom(materializer.GetType()), "typeof(ODataEntityMaterializer).IsAssignableFrom(materializer.GetType())");
     return(ODataEntityMaterializer.ListAsElementType <T, TTarget>((ODataEntityMaterializer)materializer, source));
 }
 /// <summary>Enumerates casting each element to a type.</summary>
 /// <typeparam name="T">Element type to enumerate over.</typeparam>
 /// <param name="source">Element source.</param>
 /// <returns>
 /// An IEnumerable&lt;T&gt; that iterates over the specified <paramref name="source"/>.
 /// </returns>
 /// <remarks>
 /// This method should be unnecessary with .NET 4.0 covariance support.
 /// </remarks>
 internal static IEnumerable <T> EnumerateAsElementType <T>(IEnumerable source)
 {
     return(ODataEntityMaterializer.EnumerateAsElementType <T>(source));
 }
 /// <summary>Materializes an entry without including in-lined expanded links.</summary>
 /// <param name="materializer">Materializer under which materialization should take place.</param>
 /// <param name="entry">Entry with object to materialize.</param>
 /// <param name="expectedEntryType">Expected type for the entry.</param>
 /// <returns>The materialized instance.</returns>
 internal static object ShallowMaterializePlan(object materializer, object entry, Type expectedEntryType)
 {
     Debug.Assert(typeof(ODataEntityMaterializer).IsAssignableFrom(materializer.GetType()), "typeof(ODataEntityMaterializer).IsAssignableFrom(materializer.GetType())");
     Debug.Assert(entry.GetType() == typeof(ODataEntry), "entry.GetType() == typeof(ODataEntry)");
     return(ODataEntityMaterializer.ShallowMaterializePlan((ODataEntityMaterializer)materializer, MaterializerEntry.GetEntry((ODataEntry)entry), expectedEntryType));
 }
示例#11
0
        /// <summary>
        /// Applies the values of the <paramref name="items"/> enumeration to the
        /// <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="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>
        /// <param name="isContinuation">Whether this is a continuation request.</param>
        internal void ApplyItemsToCollection(
            MaterializerEntry entry,
            ClientPropertyAnnotation property,
            IEnumerable items,
            Uri nextLink,
            ProjectionPlan continuationPlan,
            bool isContinuation)
        {
            Debug.Assert(entry.Entry != null || entry.ForLoadProperty, "ODataResource should be non-null except for LoadProperty");
            Debug.Assert(property != null, "property != null");
            Debug.Assert(items != null, "items != null");

            IEnumerable <object> itemsEnumerable = ODataEntityMaterializer.EnumerateAsElementType <object>(items);

            // Populate the collection property with items collection.
            object collection = this.PopulateCollectionProperty(entry, property, itemsEnumerable, nextLink, continuationPlan);

            // Get collection of all non-linked elements in collection and remove them except for the ones that were obtained from the response.
            if (this.EntityTrackingAdapter.MergeOption == MergeOption.OverwriteChanges ||
                this.EntityTrackingAdapter.MergeOption == MergeOption.PreserveChanges)
            {
                var linkedItemsInCollection =
                    this.EntityTrackingAdapter
                    .EntityTracker
                    .GetLinks(entry.ResolvedObject, property.PropertyName)
                    .Select(l => new { l.Target, l.IsModified });

                if (collection != null && !property.IsDictionary)
                {
                    var nonLinkedNonReceivedItemsInCollection = ODataEntityMaterializer.EnumerateAsElementType <object>((IEnumerable)collection)
                                                                .Except(linkedItemsInCollection.Select(i => i.Target))
                                                                .Except(itemsEnumerable).ToArray();

                    // Since no link exists, we just remove the item from the collection
                    foreach (var item in nonLinkedNonReceivedItemsInCollection)
                    {
                        property.RemoveValue(collection, item);
                    }
                }

                // When the first time a property or collection is being loaded, we remove all items other than the ones that we receive.
                if (!isContinuation)
                {
                    IEnumerable <object> itemsToRemove;

                    if (this.EntityTrackingAdapter.MergeOption == MergeOption.OverwriteChanges)
                    {
                        itemsToRemove = linkedItemsInCollection.Select(i => i.Target);
                    }
                    else
                    {
                        Debug.Assert(
                            this.EntityTrackingAdapter.MergeOption == MergeOption.PreserveChanges,
                            "this.EntityTrackingAdapter.MergeOption == MergeOption.PreserveChanges");

                        itemsToRemove = linkedItemsInCollection
                                        .Where(i => !i.IsModified)
                                        .Select(i => i.Target);
                    }

                    itemsToRemove = itemsToRemove.Except(itemsEnumerable);

                    foreach (var item in itemsToRemove)
                    {
                        if (collection != null)
                        {
                            property.RemoveValue(collection, item);
                        }

                        this.EntityTrackingAdapter.MaterializationLog.RemovedLink(entry, property.PropertyName, item);
                    }
                }
            }
        }
示例#12
0
 internal object Run(ODataEntityMaterializer materializer, ODataEntry entry, Type expectedType)
 {
     return(this.Plan(materializer, entry, expectedType));
 }
示例#13
0
 internal object Run(ODataEntityMaterializer materializer, ODataEntry entry, Type expectedType)
 {
     return this.Plan(materializer, entry, expectedType);
 }