/// <summary>
        /// Gets the expected query value for the action request
        /// </summary>
        /// <param name="initialExpectedResults">Initial expected values for an action</param>
        /// <param name="parameterValues">Parameter values for the action</param>
        /// <returns>A query Value that is the expected value</returns>
        public QueryValue GetExpectedQueryValue(QueryValue initialExpectedResults, params QueryValue[] parameterValues)
        {
            ExceptionUtilities.CheckArgumentNotNull(initialExpectedResults, "initialExpectedResults");

            QueryStructuralValue initialStructuralValue = initialExpectedResults as QueryStructuralValue;

            ExceptionUtilities.CheckArgumentNotNull(initialStructuralValue, "initialStructuralValue");

            QueryScalarValue initialScalarValue = initialStructuralValue.GetScalarValue(this.IntegerProperty);

            ExceptionUtilities.CheckArgumentNotNull(initialScalarValue, "initialScalarValue");

            int intPropertyValue = (int)initialScalarValue.Value;

            ExceptionUtilities.CheckArgumentNotNull(intPropertyValue, "intPropertyValue");

            if (intPropertyValue != int.MaxValue)
            {
                initialStructuralValue.SetPrimitiveValue(this.IntegerProperty, intPropertyValue + 1);
            }
            else
            {
                initialStructuralValue.SetPrimitiveValue(this.IntegerProperty, 0);
            }

            return(initialStructuralValue);
        }
Пример #2
0
        /// <summary>
        /// Gets a queryExpression that represents a Query to an existing entity
        /// </summary>
        /// <param name="entityParameter">The LinqParameterExpression which represents the root parameter</param>
        /// <param name="existingEntity">The structural value representing an existing entity</param>
        /// <returns>A QueryExpression representing a query to an existing entity</returns>
        protected static QueryExpression GetExistingEntityKeyComparisonExpression(QueryExpression entityParameter, QueryStructuralValue existingEntity)
        {
            QueryExpression keyFilterExpression = null;
            QueryEntityType entityType          = existingEntity.Type as QueryEntityType;

            foreach (var keyProperty in entityType.EntityType.AllKeyProperties)
            {
                var queryProperty = entityType.Properties.SingleOrDefault(p => p.Name == keyProperty.Name);
                ExceptionUtilities.CheckObjectNotNull(queryProperty, "Could not find property with name '{0}' on type '{1}'", keyProperty.Name, entityType);

                var             value          = existingEntity.GetScalarValue(keyProperty.Name);
                QueryExpression keyComparision = entityParameter.Property(keyProperty.Name).EqualTo(CommonQueryBuilder.Constant(value));

                if (keyFilterExpression == null)
                {
                    keyFilterExpression = keyComparision;
                }
                else
                {
                    keyFilterExpression = CommonQueryBuilder.And(keyFilterExpression, keyComparision);
                }
            }

            return(keyFilterExpression);
        }
Пример #3
0
        /// <summary>
        /// Generates the next link for an expanded feed.
        /// </summary>
        /// <param name="containingEntity">The containing entity.</param>
        /// <param name="navigation">The expanded navigation property.</param>
        /// <param name="lastEntityValue">The last entity value.</param>
        /// <returns>
        /// The expected next link
        /// </returns>
        public string GenerateExpandedNextLink(EntityInstance containingEntity, NavigationPropertyInstance navigation, QueryStructuralValue lastEntityValue)
        {
            ExceptionUtilities.CheckArgumentNotNull(containingEntity, "containingEntity");
            ExceptionUtilities.CheckArgumentNotNull(navigation, "navigation");
            ExceptionUtilities.CheckArgumentNotNull(lastEntityValue, "lastEntityValue");

            var navigationUriString = ((ExpandedLink)navigation.Value).UriString;

            if (string.IsNullOrEmpty(navigationUriString))
            {
                navigationUriString = UriHelpers.ConcatenateUriSegments(containingEntity.EditLink, navigation.Name);
            }

            var skipTokenValues = new List <object>();

            foreach (var keyProperty in lastEntityValue.Type.Properties.Where(p => p.IsPrimaryKey))
            {
                skipTokenValues.Add(lastEntityValue.GetScalarValue(keyProperty.Name).Value);
            }

            var skiptoken = this.BuildSkipTokenFromValues(skipTokenValues);

            var nextLinkUri = new ODataUri(new UnrecognizedSegment(navigationUriString));

            nextLinkUri.SkipToken = skiptoken;

            return(this.UriToStringConverter.ConvertToString(nextLinkUri));
        }
Пример #4
0
        private bool AllKeysMatch(QueryStructuralValue element, Dictionary <string, QueryScalarValue> primaryKeyValuesDictionary)
        {
            var allKeysMatch = true;

            foreach (var entry in primaryKeyValuesDictionary)
            {
                var elementKeyPropertyValue = element.GetScalarValue(entry.Key);
                if (!(bool)entry.Value.EqualTo(elementKeyPropertyValue).Value)
                {
                    allKeysMatch = false;
                    break;
                }
            }

            return(allKeysMatch);
        }
Пример #5
0
        /// <summary>
        /// Factory method to create the <see cref="LinqToAstoriaKeyExpression"/>.
        /// </summary>
        /// <param name="source">The source query.</param>
        /// <param name="instance">The instance to get key values from.</param>
        /// <returns>The <see cref="QueryExpression"/> with a key matching the values of the given instance.</returns>
        public static LinqToAstoriaKeyExpression Key(this QueryExpression source, QueryStructuralValue instance)
        {
            ExceptionUtilities.CheckArgumentNotNull(source, "source");
            ExceptionUtilities.CheckArgumentNotNull(instance, "instance");

            var entityType = instance.Type as QueryEntityType;

            ExceptionUtilities.CheckObjectNotNull(entityType, "Given structural instance was not an entity. Type was: {0}", instance.Type);

            var key = new List <KeyValuePair <QueryProperty, QueryConstantExpression> >();

            foreach (var keyProperty in entityType.EntityType.AllKeyProperties)
            {
                var queryProperty = entityType.Properties.SingleOrDefault(p => p.Name == keyProperty.Name);
                ExceptionUtilities.CheckObjectNotNull(queryProperty, "Could not find property with name '{0}' on type '{1}'", keyProperty.Name, entityType);

                var value = instance.GetScalarValue(keyProperty.Name);

                key.Add(new KeyValuePair <QueryProperty, QueryConstantExpression>(queryProperty, CommonQueryBuilder.Constant(value)));
            }

            return(new LinqToAstoriaKeyExpression(source, key, entityType.CreateCollectionType()));
        }
Пример #6
0
        /// <summary>
        /// Constructs a strong etag using property values from the given instance
        /// </summary>
        /// <param name="converter">The converter to extend</param>
        /// <param name="instance">The instance to get property values from</param>
        /// <returns>A strong etag</returns>
        public static string ConstructStrongETag(this IODataLiteralConverter converter, QueryStructuralValue instance)
        {
            ExceptionUtilities.CheckArgumentNotNull(instance, "instance");

            var entityType = instance.Type as QueryEntityType;

            ExceptionUtilities.CheckObjectNotNull(entityType, "Given structural instance was not an entity. Type was: {0}", instance.Type);

            var properties = entityType.EntityType.AllProperties.Where(p => p.Annotations.OfType <ConcurrencyTokenAnnotation>().Any()).ToList();

            if (!properties.Any())
            {
                return(null);
            }

            var values = properties.Select(p => instance.GetScalarValue(p.Name));

            // TODO: pad any fixed-length fields
            var pieces = values.Select(v => Uri.EscapeDataString(converter.SerializePrimitive(v.Value)));
            var etag   = string.Format(CultureInfo.InvariantCulture, "\"{0}\"", string.Join(",", pieces.ToArray()));

            return(etag);
        }
        /// <summary>
        /// Generates the next link for an expanded feed.
        /// </summary>
        /// <param name="containingEntity">The containing entity.</param>
        /// <param name="navigation">The expanded navigation property.</param>
        /// <param name="lastEntityValue">The last entity value.</param>
        /// <returns>
        /// The expected next link
        /// </returns>
        public string GenerateExpandedNextLink(EntityInstance containingEntity, NavigationPropertyInstance navigation, QueryStructuralValue lastEntityValue)
        {
            ExceptionUtilities.CheckArgumentNotNull(containingEntity, "containingEntity");
            ExceptionUtilities.CheckArgumentNotNull(navigation, "navigation");
            ExceptionUtilities.CheckArgumentNotNull(lastEntityValue, "lastEntityValue");

            var navigationUriString = ((ExpandedLink)navigation.Value).UriString;
            if (string.IsNullOrEmpty(navigationUriString))
            {
                navigationUriString = UriHelpers.ConcatenateUriSegments(containingEntity.EditLink, navigation.Name);
            }

            var skipTokenValues = new List<object>();
            foreach (var keyProperty in lastEntityValue.Type.Properties.Where(p => p.IsPrimaryKey))
            {
                skipTokenValues.Add(lastEntityValue.GetScalarValue(keyProperty.Name).Value);
            }

            var skiptoken = this.BuildSkipTokenFromValues(skipTokenValues);

            var nextLinkUri = new ODataUri(new UnrecognizedSegment(navigationUriString));
            nextLinkUri.SkipToken = skiptoken;

            return this.UriToStringConverter.ConvertToString(nextLinkUri);
        }
        /// <summary>
        /// Factory method to create the <see cref="LinqToAstoriaKeyExpression"/>.
        /// </summary>
        /// <param name="source">The source query.</param>
        /// <param name="instance">The instance to get key values from.</param>
        /// <returns>The <see cref="QueryExpression"/> with a key matching the values of the given instance.</returns>
        public static LinqToAstoriaKeyExpression Key(this QueryExpression source, QueryStructuralValue instance)
        {
            ExceptionUtilities.CheckArgumentNotNull(source, "source");
            ExceptionUtilities.CheckArgumentNotNull(instance, "instance");

            var entityType = instance.Type as QueryEntityType;
            ExceptionUtilities.CheckObjectNotNull(entityType, "Given structural instance was not an entity. Type was: {0}", instance.Type);

            var key = new List<KeyValuePair<QueryProperty, QueryConstantExpression>>();
            foreach (var keyProperty in entityType.EntityType.AllKeyProperties)
            {
                var queryProperty = entityType.Properties.SingleOrDefault(p => p.Name == keyProperty.Name);
                ExceptionUtilities.CheckObjectNotNull(queryProperty, "Could not find property with name '{0}' on type '{1}'", keyProperty.Name, entityType);

                var value = instance.GetScalarValue(keyProperty.Name);

                key.Add(new KeyValuePair<QueryProperty, QueryConstantExpression>(queryProperty, CommonQueryBuilder.Constant(value)));
            }

            return new LinqToAstoriaKeyExpression(source, key, entityType.CreateCollectionType());
        }
        private void CompareValues(QueryStructuralValue instance, IEnumerable<NamedValue> namedValues, string propertyPath)
        {
            foreach (QueryProperty property in instance.Type.Properties)
            {
                string childPropertyPath = property.Name;
                if (propertyPath != null)
                {
                    childPropertyPath = propertyPath + "." + property.Name;
                }

                // Skip if its an EntityType, this only handles structural types
                var queryEntityType = property.PropertyType as QueryEntityType;
                if (queryEntityType != null)
                {
                    continue;
                }

                var collectionType = property.PropertyType as QueryCollectionType;
                var scalarType = property.PropertyType as QueryScalarType;
                var complexDataType = property.PropertyType as QueryComplexType;

                QueryEntityType collectionQueryElementType = null;
                if (collectionType != null)
                {
                    collectionQueryElementType = collectionType.ElementType as QueryEntityType;
                }

                // Skip if its a collection of QueryEntityType
                if (collectionQueryElementType != null)
                {
                    continue;
                }

                if (scalarType != null)
                {
                    // The following code block handles the case where the value is server generated.
                    // For instance, server generated Keys would fail so if a property is marked as being server generated
                    // we make sure to remove that property from the list of properties to verify
                    MemberProperty memberProperty;
                    var instanceEntityType = instance.Type as QueryEntityType;
                    if (instanceEntityType != null)
                    {
                        memberProperty = instanceEntityType.EntityType.AllProperties.SingleOrDefault(p => p.Name == property.Name);
                    }
                    else
                    {
                        memberProperty = ((QueryComplexType)instance.Type).ComplexType.Properties.SingleOrDefault(p => p.Name == property.Name);
                    }

                    if (memberProperty != null && memberProperty.Annotations.OfType<StoreGeneratedPatternAnnotation>().Any())
                    {
                        // TODO: be more fine-grained about whether this is an update or insert (ie, look at the annotation's property values)
                        this.unusedNamedValuePaths.Remove(childPropertyPath);
                        continue;
                    }

                    NamedValue primitivePropertyNamedValue = namedValues.SingleOrDefault(nv => nv.Name == childPropertyPath);
                    if (primitivePropertyNamedValue != null)
                    {
                        var queryValue = instance.GetScalarValue(property.Name);
                        this.WriteErrorIfNotEqual(childPropertyPath, primitivePropertyNamedValue.Value, queryValue);
                        this.unusedNamedValuePaths.Remove(childPropertyPath);
                    }
                }
                else if (collectionType != null)
                {
                    List<NamedValue> bagNamedValues = namedValues.Where(nv => nv.Name.StartsWith(childPropertyPath + ".", StringComparison.Ordinal)).ToList();
                    if (bagNamedValues.Any())
                    {
                        this.CompareBagProperty(instance, property, collectionType.ElementType, childPropertyPath, bagNamedValues);
                    }
                    else
                    {
                        this.CompareBagPropertyWithNullOrEmpty(instance, property, childPropertyPath, namedValues);
                    }
                }
                else if (complexDataType != null)
                {
                    // NOTE: we cannot assert that it is complex/primitive/bag, because there may be new query types added in other assemblies that we know nothing about here
                    QueryStructuralValue complexTypeValue = instance.GetStructuralValue(property.Name);

                    List<NamedValue> complexInstanceNamedValues = namedValues.Where(nv => nv.Name.StartsWith(childPropertyPath + ".", StringComparison.Ordinal)).ToList();
                    if (complexInstanceNamedValues.Any())
                    {
                        if (!this.WriteErrorIfNull(childPropertyPath, complexTypeValue))
                        {
                            this.CompareValues(complexTypeValue, complexInstanceNamedValues, childPropertyPath);
                        }
                    }
                    else
                    {
                        // Check for null case
                        List<NamedValue> exactMatches = namedValues.Where(nv => nv.Name == childPropertyPath).ToList();
                        ExceptionUtilities.Assert(exactMatches.Count < 2, "Should only find at most one property path {0} when looking for null value", childPropertyPath);
                        if (exactMatches.Count == 1)
                        {
                            ExceptionUtilities.Assert(
                                exactMatches[0].Value == null,
                                "Named value at path '{0}' was unexpectedly non-null. Value was '{1}'",
                                childPropertyPath,
                                exactMatches[0].Value);

                            QueryValue queryValue = instance.GetValue(property.Name);
                            this.WriteErrorIfNotNull(childPropertyPath, queryValue);
                            this.unusedNamedValuePaths.Remove(childPropertyPath);
                        }
                    }
                }
            }
        }
Пример #10
0
        private static ODataUri GetTopLevelUri(QueryStructuralValue entity)
        {
            ExceptionUtilities.CheckArgumentNotNull(entity, "entity");
            QueryEntityType entityType = entity.Type as QueryEntityType;

            ExceptionUtilities.CheckObjectNotNull(entityType, "Given structural value was not an entity type");

            var setSegment = ODataUriBuilder.EntitySet(entityType.EntitySet);
            var keyValues  = entityType.EntityType.AllKeyProperties.Select(k => new NamedValue(k.Name, entity.GetScalarValue(k.Name).Value));
            var keySegment = ODataUriBuilder.Key(entityType.EntityType, keyValues);

            return(new ODataUri(setSegment, keySegment));
        }
        private QueryStructuralValue CloneStructuralValue(Dictionary<QueryStructuralValue, QueryStructuralValue> identityMap, QueryStructuralValue qsv)
        {
            if (qsv.IsNull)
            {
                return qsv;
            }

            QueryStructuralValue clonedValue;

            if (identityMap.TryGetValue(qsv, out clonedValue))
            {
                return clonedValue;
            }

            clonedValue = qsv.Type.CreateNewInstance();
            identityMap.Add(qsv, clonedValue);
      
            foreach (var m in qsv.Type.Properties)
            {
                // copy scalar properties
                if (m.PropertyType is QueryScalarType)
                {
                    clonedValue.SetValue(m.Name, qsv.GetScalarValue(m.Name));
                    continue;
                }

                // copy stream properties
                if (m.PropertyType is AstoriaQueryStreamType)
                {
                    if (m.Name.Contains("DefaultStream"))
                    {
                        clonedValue.SetDefaultStreamValue(qsv.GetDefaultStreamValue());
                    }
                    else
                    {
                        clonedValue.SetStreamValue(m.Name, qsv.GetStreamValue(m.Name));
                    }

                    continue;
                }

                var qst = m.PropertyType as QueryStructuralType;
                if (m.PropertyType is QueryStructuralType)
                {
                    if (!qst.IsValueType)
                    {
                        // skip reference types, clone everything else
                        continue;
                    }

                    clonedValue.SetValue(m.Name, this.CloneStructuralValue(identityMap, qsv.GetStructuralValue(m.Name)));
                }

                var qct = m.PropertyType as QueryCollectionType;
                if (qct != null)
                {
                    var elementStructuralType = qct.ElementType as QueryStructuralType;
                    if (elementStructuralType != null)
                    {
                        if (!elementStructuralType.IsValueType)
                        {
                            // skip collections of reference types, clone everything else
                            continue;
                        }
                    }

                    clonedValue.SetValue(m.Name, this.CloneCollectionValue(identityMap, qsv.GetCollectionValue(m.Name)));
                }
            }

            return clonedValue;
        }
Пример #12
0
        private void CompareValues(QueryStructuralValue instance, IEnumerable <NamedValue> namedValues, string propertyPath)
        {
            foreach (QueryProperty property in instance.Type.Properties)
            {
                string childPropertyPath = property.Name;
                if (propertyPath != null)
                {
                    childPropertyPath = propertyPath + "." + property.Name;
                }

                // Skip if its an EntityType, this only handles structural types
                var queryEntityType = property.PropertyType as QueryEntityType;
                if (queryEntityType != null)
                {
                    continue;
                }

                var collectionType  = property.PropertyType as QueryCollectionType;
                var scalarType      = property.PropertyType as QueryScalarType;
                var complexDataType = property.PropertyType as QueryComplexType;

                QueryEntityType collectionQueryElementType = null;
                if (collectionType != null)
                {
                    collectionQueryElementType = collectionType.ElementType as QueryEntityType;
                }

                // Skip if its a collection of QueryEntityType
                if (collectionQueryElementType != null)
                {
                    continue;
                }

                if (scalarType != null)
                {
                    // The following code block handles the case where the value is server generated.
                    // For instance, server generated Keys would fail so if a property is marked as being server generated
                    // we make sure to remove that property from the list of properties to verify
                    MemberProperty memberProperty;
                    var            instanceEntityType = instance.Type as QueryEntityType;
                    if (instanceEntityType != null)
                    {
                        memberProperty = instanceEntityType.EntityType.AllProperties.SingleOrDefault(p => p.Name == property.Name);
                    }
                    else
                    {
                        memberProperty = ((QueryComplexType)instance.Type).ComplexType.Properties.SingleOrDefault(p => p.Name == property.Name);
                    }

                    if (memberProperty != null && memberProperty.Annotations.OfType <StoreGeneratedPatternAnnotation>().Any())
                    {
                        // TODO: be more fine-grained about whether this is an update or insert (ie, look at the annotation's property values)
                        this.unusedNamedValuePaths.Remove(childPropertyPath);
                        continue;
                    }

                    NamedValue primitivePropertyNamedValue = namedValues.SingleOrDefault(nv => nv.Name == childPropertyPath);
                    if (primitivePropertyNamedValue != null)
                    {
                        var queryValue = instance.GetScalarValue(property.Name);
                        this.WriteErrorIfNotEqual(childPropertyPath, primitivePropertyNamedValue.Value, queryValue);
                        this.unusedNamedValuePaths.Remove(childPropertyPath);
                    }
                }
                else if (collectionType != null)
                {
                    List <NamedValue> bagNamedValues = namedValues.Where(nv => nv.Name.StartsWith(childPropertyPath + ".", StringComparison.Ordinal)).ToList();
                    if (bagNamedValues.Any())
                    {
                        this.CompareBagProperty(instance, property, collectionType.ElementType, childPropertyPath, bagNamedValues);
                    }
                    else
                    {
                        this.CompareBagPropertyWithNullOrEmpty(instance, property, childPropertyPath, namedValues);
                    }
                }
                else if (complexDataType != null)
                {
                    // NOTE: we cannot assert that it is complex/primitive/bag, because there may be new query types added in other assemblies that we know nothing about here
                    QueryStructuralValue complexTypeValue = instance.GetStructuralValue(property.Name);

                    List <NamedValue> complexInstanceNamedValues = namedValues.Where(nv => nv.Name.StartsWith(childPropertyPath + ".", StringComparison.Ordinal)).ToList();
                    if (complexInstanceNamedValues.Any())
                    {
                        if (!this.WriteErrorIfNull(childPropertyPath, complexTypeValue))
                        {
                            this.CompareValues(complexTypeValue, complexInstanceNamedValues, childPropertyPath);
                        }
                    }
                    else
                    {
                        // Check for null case
                        List <NamedValue> exactMatches = namedValues.Where(nv => nv.Name == childPropertyPath).ToList();
                        ExceptionUtilities.Assert(exactMatches.Count < 2, "Should only find at most one property path {0} when looking for null value", childPropertyPath);
                        if (exactMatches.Count == 1)
                        {
                            ExceptionUtilities.Assert(
                                exactMatches[0].Value == null,
                                "Named value at path '{0}' was unexpectedly non-null. Value was '{1}'",
                                childPropertyPath,
                                exactMatches[0].Value);

                            QueryValue queryValue = instance.GetValue(property.Name);
                            this.WriteErrorIfNotNull(childPropertyPath, queryValue);
                            this.unusedNamedValuePaths.Remove(childPropertyPath);
                        }
                    }
                }
            }
        }
Пример #13
0
 /// <summary>
 /// Returns the key property values for the given entity instance
 /// </summary>
 /// <param name="instance">The instance to get key property values from</param>
 /// <returns>The key values of the given instance</returns>
 public static IEnumerable <NamedValue> GetKeyPropertyValues(this QueryStructuralValue instance)
 {
     ExceptionUtilities.CheckArgumentNotNull(instance, "instance");
     return(instance.Type.Properties.Where(p => p.IsPrimaryKey).Select(p => new NamedValue(p.Name, instance.GetScalarValue(p.Name).Value)));
 }
Пример #14
0
        /// <summary>
        /// Synchronizes the entity represented by the given query structural value
        /// </summary>
        /// <param name="synchronizer">The synchronizer to extend</param>
        /// <param name="continuation">The continuation to use</param>
        /// <param name="existingEntity">The representation of the entity to synchronize</param>
        public static void SynchronizeEntity(this IAsyncDataSynchronizer synchronizer, IAsyncContinuation continuation, QueryStructuralValue existingEntity)
        {
            ExceptionUtilities.CheckArgumentNotNull(synchronizer, "synchronizer");
            ExceptionUtilities.CheckArgumentNotNull(continuation, "continuation");
            ExceptionUtilities.CheckArgumentNotNull(existingEntity, "existingEntity");

            var entityType = existingEntity.Type as QueryEntityType;

            ExceptionUtilities.CheckObjectNotNull(entityType, "Given structural value was not an entity type");
            string entitySetName = entityType.EntitySet.Name;
            var    keyValues     = entityType.Properties.Where(p => p.IsPrimaryKey).Select(p => new NamedValue(p.Name, existingEntity.GetScalarValue(p.Name).Value));

            synchronizer.SynchronizeEntityInstanceGraph(continuation, entitySetName, keyValues);
        }
        /// <summary>
        /// Generates the expected next link for a top-level feed
        /// </summary>
        /// <param name="requestUri">The request URI.</param>
        /// <param name="pageSize">The page size.</param>
        /// <param name="lastEntityValue">The last entity value.</param>
        /// <returns>
        /// The expected next link
        /// </returns>
        public string GenerateNextLink(ODataUri requestUri, int pageSize, QueryStructuralValue lastEntityValue)
        {
            ExceptionUtilities.CheckArgumentNotNull(requestUri, "requestUri");
            ExceptionUtilities.CheckArgumentNotNull(lastEntityValue, "lastEntityValue");
            
            var queryBasedUri = requestUri as QueryBasedODataUri;
            ExceptionUtilities.CheckObjectNotNull(queryBasedUri, "Only uris which were generated from queries are supported");
            
            var skipTokenValues = new List<object>();
            foreach (var keySelector in queryBasedUri.OrderByExpressions.SelectMany(o => o.KeySelectors))
            {
                skipTokenValues.Add(this.EvaluateLambdaForEntity(lastEntityValue, keySelector));
            }

            foreach (var keyProperty in lastEntityValue.Type.Properties.Where(p => p.IsPrimaryKey))
            {
                skipTokenValues.Add(lastEntityValue.GetScalarValue(keyProperty.Name).Value);
            }

            var skiptoken = this.BuildSkipTokenFromValues(skipTokenValues);

            // copy request uri segments exactly
            var nextLinkUri = new ODataUri(requestUri.Segments);

            // copy over $orderby, $filter, $expand, $select, and $inlinecount
            nextLinkUri.OrderBy = ModifyQueryOptionToMatchProduct(requestUri.OrderBy);
            nextLinkUri.Filter = ModifyQueryOptionToMatchProduct(requestUri.Filter);
            nextLinkUri.ExpandSegments = requestUri.ExpandSegments;
            nextLinkUri.SelectSegments = requestUri.SelectSegments;

            string inlineCountValue;
            if (requestUri.TryGetInlineCountValue(out inlineCountValue))
            {
                nextLinkUri.InlineCount = inlineCountValue;
            }

            // add the $skiptoken generated above
            nextLinkUri.SkipToken = skiptoken;

            // generate a new $top value
            if (requestUri.Top.HasValue)
            {
                var top = requestUri.Top.Value - pageSize;
                if (top > 0)
                {
                    nextLinkUri.Top = top;
                }
            }

            if (requestUri.IsServiceOperation())
            {
                var functionSegment = requestUri.Segments.OfType<FunctionSegment>().Last();
                foreach (var paramName in functionSegment.Function.Parameters.Select(p => p.Name))
                {
                    string paramValue;
                    if (requestUri.CustomQueryOptions.TryGetValue(paramName, out paramValue))
                    {
                        nextLinkUri.CustomQueryOptions[paramName] = paramValue;
                    }
                }
            }

            return this.UriToStringConverter.ConvertToString(nextLinkUri);
        }
Пример #16
0
 private EntityDataKey GetEntityKey(QueryStructuralValue entity)
 {
     ExceptionUtilities.CheckArgumentNotNull(entity, "entity");
     return(EntityDataKey.CreateFromValues(entity.Type.Properties.Where(p => p.IsPrimaryKey).Select(p => new NamedValue(p.Name, entity.GetScalarValue(p.Name).Value))));
 }
Пример #17
0
        private static ODataUri GetTopLevelUri(QueryStructuralValue entity)
        {
            ExceptionUtilities.CheckArgumentNotNull(entity, "entity");
            QueryEntityType entityType = entity.Type as QueryEntityType;
            ExceptionUtilities.CheckObjectNotNull(entityType, "Given structural value was not an entity type");

            var setSegment = ODataUriBuilder.EntitySet(entityType.EntitySet);
            var keyValues = entityType.EntityType.AllKeyProperties.Select(k => new NamedValue(k.Name, entity.GetScalarValue(k.Name).Value));
            var keySegment = ODataUriBuilder.Key(entityType.EntityType, keyValues);

            return new ODataUri(setSegment, keySegment);
        }
Пример #18
0
        /// <summary>
        /// Generates the expected next link for a top-level feed
        /// </summary>
        /// <param name="requestUri">The request URI.</param>
        /// <param name="pageSize">The page size.</param>
        /// <param name="lastEntityValue">The last entity value.</param>
        /// <returns>
        /// The expected next link
        /// </returns>
        public string GenerateNextLink(ODataUri requestUri, int pageSize, QueryStructuralValue lastEntityValue)
        {
            ExceptionUtilities.CheckArgumentNotNull(requestUri, "requestUri");
            ExceptionUtilities.CheckArgumentNotNull(lastEntityValue, "lastEntityValue");

            var queryBasedUri = requestUri as QueryBasedODataUri;

            ExceptionUtilities.CheckObjectNotNull(queryBasedUri, "Only uris which were generated from queries are supported");

            var skipTokenValues = new List <object>();

            foreach (var keySelector in queryBasedUri.OrderByExpressions.SelectMany(o => o.KeySelectors))
            {
                skipTokenValues.Add(this.EvaluateLambdaForEntity(lastEntityValue, keySelector));
            }

            foreach (var keyProperty in lastEntityValue.Type.Properties.Where(p => p.IsPrimaryKey))
            {
                skipTokenValues.Add(lastEntityValue.GetScalarValue(keyProperty.Name).Value);
            }

            var skiptoken = this.BuildSkipTokenFromValues(skipTokenValues);

            // copy request uri segments exactly
            var nextLinkUri = new ODataUri(requestUri.Segments);

            // copy over $orderby, $filter, $expand, $select, and $inlinecount
            nextLinkUri.OrderBy        = ModifyQueryOptionToMatchProduct(requestUri.OrderBy);
            nextLinkUri.Filter         = ModifyQueryOptionToMatchProduct(requestUri.Filter);
            nextLinkUri.ExpandSegments = requestUri.ExpandSegments;
            nextLinkUri.SelectSegments = requestUri.SelectSegments;

            string inlineCountValue;

            if (requestUri.TryGetInlineCountValue(out inlineCountValue))
            {
                nextLinkUri.InlineCount = inlineCountValue;
            }

            // add the $skiptoken generated above
            nextLinkUri.SkipToken = skiptoken;

            // generate a new $top value
            if (requestUri.Top.HasValue)
            {
                var top = requestUri.Top.Value - pageSize;
                if (top > 0)
                {
                    nextLinkUri.Top = top;
                }
            }

            if (requestUri.IsServiceOperation())
            {
                var functionSegment = requestUri.Segments.OfType <FunctionSegment>().Last();
                foreach (var paramName in functionSegment.Function.Parameters.Select(p => p.Name))
                {
                    string paramValue;
                    if (requestUri.CustomQueryOptions.TryGetValue(paramName, out paramValue))
                    {
                        nextLinkUri.CustomQueryOptions[paramName] = paramValue;
                    }
                }
            }

            return(this.UriToStringConverter.ConvertToString(nextLinkUri));
        }
Пример #19
0
        /// <summary>
        /// Gets a queryExpression that represents a Query to an existing entity
        /// </summary>
        /// <param name="entityParameter">The LinqParameterExpression which represents the root parameter</param>
        /// <param name="existingEntity">The structural value representing an existing entity</param>
        /// <returns>A QueryExpression representing a query to an existing entity</returns>
        protected static QueryExpression GetExistingEntityKeyComparisonExpression(QueryExpression entityParameter, QueryStructuralValue existingEntity)
        {
            QueryExpression keyFilterExpression = null;
            QueryEntityType entityType = existingEntity.Type as QueryEntityType;
            foreach (var keyProperty in entityType.EntityType.AllKeyProperties)
            {
                var queryProperty = entityType.Properties.SingleOrDefault(p => p.Name == keyProperty.Name);
                ExceptionUtilities.CheckObjectNotNull(queryProperty, "Could not find property with name '{0}' on type '{1}'", keyProperty.Name, entityType);

                var value = existingEntity.GetScalarValue(keyProperty.Name);
                QueryExpression keyComparision = entityParameter.Property(keyProperty.Name).EqualTo(CommonQueryBuilder.Constant(value));

                if (keyFilterExpression == null)
                {
                    keyFilterExpression = keyComparision;
                }
                else
                {
                    keyFilterExpression = CommonQueryBuilder.And(keyFilterExpression, keyComparision);
                }
            }

            return keyFilterExpression;
        }