예제 #1
0
        public static string TranslateKeyValueToString(this KeySegment segment)
        {
            Contract.Assert(segment != null);

            IEdmEntityType entityType = segment.EdmType as IEdmEntityType;

            Contract.Assert(entityType != null);

            var keys = segment.Keys.ToList();

            if (keys.Count < 2)
            {
                var  keyValue      = keys.First();
                bool isDeclaredKey = entityType.Key().Any(k => k.Name == keyValue.Key);

                // alternate keys are always using the "key=value"
                if (isDeclaredKey)
                {
                    return(String.Join(
                               ",",
                               keys.Select(keyValuePair =>
                                           TranslateKeySegmentValue(keyValuePair.Value)).ToArray()));
                }
            }

            return(String.Join(
                       ",",
                       keys.Select(keyValuePair =>
                                   (keyValuePair.Key +
                                    "=" +
                                    TranslateKeySegmentValue(keyValuePair.Value))).ToArray()));
        }
예제 #2
0
        /// <summary>
        ///A test for GetValue
        ///</summary>
        void GetValueTestHelper <E, T>(E e, T tail)
            where E : class
            where T : ITrashable
        {
            KeySegment <E, T> target =
                new KeySegment <E, T>()
            {
                _elementReference = new WeakKey <E> {
                    _elementReference = new WeakReference(e)
                },
                _tail = tail
            }
            ;
            E value = null; // TODO: Initialize to an appropriate value

            Assert.IsTrue(target.GetValue(out value, true));
            Assert.AreEqual(e, value);

            ((WeakReference)target._elementReference._elementReference).Target = null;

            Assert.IsFalse(target.GetValue(out value, true));

            ((WeakReference)target._elementReference._elementReference).Target = WeakKey <E> .NullValue;
            Assert.IsTrue(target.GetValue(out value, true));
            Assert.AreEqual(null, value);

            target._elementReference._elementReference = e;
            Assert.IsTrue(target.GetValue(out value, false));
            Assert.AreEqual(e, value);
        }
예제 #3
0
        public void SetIsCopiedFromPreviousSegment()
        {
            var        set     = ModelBuildingHelpers.BuildValidEntitySet();
            KeySegment segment = new KeySegment(Key, set.EntityType(), set);

            segment.NavigationSource.Should().BeSameAs(set);
        }
예제 #4
0
        private static KeySegment BuildKeySegment(IEdmEntityType entityType, IEdmEntitySetBase entitySet, object target)
        {
            if (entityType == null)
            {
                throw new ArgumentNullException("entityType");
            }

            if (entitySet == null)
            {
                throw new ArgumentNullException("entitySet");
            }

            if (target == null)
            {
                throw new ArgumentNullException("target");
            }

            KeySegment keySegment = new KeySegment(
                entityType.Key().Select(
                    (key) =>
            {
                var keyValue = target.GetType().GetProperty(key.Name).GetValue(target, null);
                return(new KeyValuePair <string, object>(key.Name, keyValue));
            }),
                entityType,
                entitySet);

            return(keySegment);
        }
예제 #5
0
        /// <summary>
        ///A test for IsGarbage
        ///</summary>
        void IsGarbageTestHelper <E>(E e)
            where E : class
        {
            var target =
                new KeySegment <E, TrashableStub>()
            {
                _elementReference = new WeakKey <E>
                {
                    _elementReference = new WeakReference(e)
                },
                _tail = new TrashableStub()
            }
            ;

            Assert.IsFalse(target.IsGarbage);

            target._tail._isGarbage = true;

            Assert.IsTrue(target.IsGarbage);

            target._tail._isGarbage = false;
            ((WeakReference)target._elementReference._elementReference).Target = null;

            Assert.IsTrue(target.IsGarbage);

            target.SetValue(null, true);

            Assert.IsFalse(target.IsGarbage);
        }
예제 #6
0
        public void TryTranslateKeySegmentTemplate_ReturnsODataKeySegment()
        {
            // Arrange
            EdmModel model = new EdmModel();

            model.AddElement(_customerType);
            model.AddElement(_container);

            IDictionary <string, string> keys = new Dictionary <string, string>
            {
                { "customerId", "{key}" }
            };

            KeySegmentTemplate            template = new KeySegmentTemplate(keys, _customerType, _customers);
            ODataTemplateTranslateContext context  = new ODataTemplateTranslateContext
            {
                RouteValues = new RouteValueDictionary(new { key = "42" }),
                Model       = model
            };

            // Act
            bool ok = template.TryTranslate(context);

            // Assert
            Assert.True(ok);
            ODataPathSegment actual     = Assert.Single(context.Segments);
            KeySegment       keySegment = Assert.IsType <KeySegment>(actual);
            var actualKey = Assert.Single(keySegment.Keys);

            Assert.Equal("customerId", actualKey.Key);
            Assert.Equal(42, actualKey.Value);
        }
예제 #7
0
        /// <summary>
        /// Translate KeySegment to linq expression.
        /// </summary>
        /// <param name="segment">The KeySegment</param>
        /// <returns>The linq expression</returns>
        public override Expression Translate(KeySegment segment)
        {
            // translate to be ResultExpressionFromEntitySetSegment.Where(id -> id == keyVale).Single()

            Type instanceType = null;

            if (segment.EdmType.TypeKind == EdmTypeKind.Primitive)
            {
                instanceType = EdmLibraryExtensions.GetPrimitiveClrType((IEdmPrimitiveTypeReference)segment.EdmType.ToTypeReference(false));
            }

            ParameterExpression parameter = Expression.Parameter(instanceType, "it");
            Expression          body      = null;

            foreach (var key in segment.Keys)
            {
                var        propertyAccessExpression = Expression.Property(parameter, instanceType, key.Key);
                Expression keyPredicate             = Expression.Equal(propertyAccessExpression, Expression.Constant(key.Value));
                if (body == null)
                {
                    body = keyPredicate;
                }
                else
                {
                    body = Expression.AndAlso(body, keyPredicate);
                }
            }

            Expression whereResult = Expression.Call(typeof(Queryable), WhereMethodName, new Type[] { instanceType }, this.ResultExpression, Expression.Quote(Expression.Lambda(body, parameter)));

            this.ResultExpression = Expression.Call(typeof(Queryable), SingleMethodName, new Type[] { instanceType }, whereResult);
            return(this.ResultExpression);
        }
예제 #8
0
        /// <summary>
        /// Handle a KeySegment
        /// </summary>
        /// <param name="segment">the segment to handle</param>
        public override void Handle(KeySegment segment)
        {
            _navigationSource = segment.NavigationSource;

            if (_pathTemplate.Last() == ODataSegmentKinds.Ref)
            {
                _pathTemplate.Insert(_pathTemplate.Count - 1, ODataSegmentKinds.Key);
            }
            else
            {
                _pathTemplate.Add(ODataSegmentKinds.Key);
            }

            string value = ConvertKeysToString(segment.Keys, segment.EdmType);

            // update the previous segment Uri literal
            if (!_pathUriLiteral.Any())
            {
                _pathUriLiteral.Add("(" + value + ")");
                return;
            }

            if (_pathUriLiteral.Last() == ODataSegmentKinds.Ref)
            {
                _pathUriLiteral[_pathUriLiteral.Count - 2] =
                    _pathUriLiteral[_pathUriLiteral.Count - 2] + "(" + value + ")";
            }
            else
            {
                _pathUriLiteral[_pathUriLiteral.Count - 1] =
                    _pathUriLiteral[_pathUriLiteral.Count - 1] + "(" + value + ")";
            }
        }
        public override string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup <string, HttpActionDescriptor> actionMap)
        {
            if (odataPath == null || controllerContext == null || actionMap == null)
            {
                return(null);
            }

            if (controllerContext.Request.Method != HttpMethod.Put)
            {
                return(null);
            }

            if (odataPath.PathTemplate != "~/entityset/key/navigation")
            {
                return(null);
            }

            KeySegment keySegment = odataPath.Segments[1] as KeySegment;

            controllerContext.RouteData.Values[ODataRouteConstants.Key] = keySegment.Keys.First().Value;

            NavigationPropertySegment navSegment = odataPath.Segments[2] as NavigationPropertySegment;

            return("PutTo" + navSegment.NavigationProperty.Name);
        }
예제 #10
0
        public void CtorKeySegmentTemplate_SetsProperties_ForCompositeKeys()
        {
            // Arrange & Act
            EdmEntityType         customerType  = new EdmEntityType("NS", "Customer");
            EdmStructuralProperty firstProperty = customerType.AddStructuralProperty("firstName", EdmPrimitiveTypeKind.String);
            EdmStructuralProperty lastProperty  = customerType.AddStructuralProperty("lastName", EdmPrimitiveTypeKind.String);

            customerType.AddKeys(firstProperty, lastProperty);
            IDictionary <string, object> keys = new Dictionary <string, object>
            {
                { "firstName", "{key1}" },
                { "lastName", "{key2}" }
            };

            KeySegment         segment  = new KeySegment(keys, customerType, null);
            KeySegmentTemplate template = new KeySegmentTemplate(segment);

            // Assert
            Assert.Collection(template.KeyMappings,
                              e =>
            {
                Assert.Equal("firstName", e.Key);
                Assert.Equal("key1", e.Value);
            },
                              e =>
            {
                Assert.Equal("lastName", e.Key);
                Assert.Equal("key2", e.Value);
            });
        }
예제 #11
0
        public void CtorKeySegmentTemplate_ForAlternateKey_SetsProperties()
        {
            // Arrange & Act
            IDictionary <string, object> keys = new Dictionary <string, object>
            {
                { "name", BuildExpression("{nameValue}") }
            };
            KeySegment keySegment = new KeySegment(keys, _customerType, _customers);

            IEdmStructuralProperty             nameProperty = _customerType.StructuralProperties().First(c => c.Name == "Name");
            IDictionary <string, IEdmProperty> properties   = new Dictionary <string, IEdmProperty>
            {
                { "name", nameProperty }
            };
            KeySegmentTemplate segmentTemplate = new KeySegmentTemplate(keySegment, properties);

            // Assert
            KeyValuePair <string, string> keyMapping = Assert.Single(segmentTemplate.KeyMappings);

            Assert.Equal("name", keyMapping.Key);
            Assert.Equal("nameValue", keyMapping.Value);

            KeyValuePair <string, IEdmProperty> keyProperty = Assert.Single(segmentTemplate.KeyProperties);

            Assert.Equal("name", keyProperty.Key);
            Assert.Equal("Name", keyProperty.Value.Name);

            Assert.Same(_customers, segmentTemplate.NavigationSource);
            Assert.Same(_customerType, segmentTemplate.EntityType);
            Assert.Equal(1, segmentTemplate.Count);
        }
        public void TryMatchMediaType_WithNonRawvalueRequest_DoesntMatchRequest()
        {
            IEdmModel      model      = ODataTestUtil.GetEdmModel();
            IEdmEntitySet  people     = model.EntityContainer.FindEntitySet("People");
            IEdmEntityType personType =
                model.SchemaElements.OfType <IEdmEntityType>().First(e => e.Name == "FormatterPerson");

            IEdmStructuralProperty ageProperty = personType.FindProperty("Age") as IEdmStructuralProperty;

            Assert.NotNull(ageProperty); // Guard
            PropertySegment propertySegment = new PropertySegment(ageProperty);

            var        keys       = new[] { new KeyValuePair <string, object>("PerId", 1) };
            KeySegment keySegment = new KeySegment(keys, personType, people);

            ODataPath path = new ODataPath(new EntitySetSegment(people), keySegment, propertySegment);
            ODataPrimitiveValueMediaTypeMapping mapping = new ODataPrimitiveValueMediaTypeMapping();
            var request = RequestFactory.Create(HttpMethod.Get, "http://localhost/People(1)/Age/");

            request.ODataContext().Path = path;

            double mapResult = mapping.TryMatchMediaType(request);

            Assert.Equal(0, mapResult);
        }
예제 #13
0
        /// <summary>
        /// Add a key value to the route data.
        /// </summary>

        public void AddKeyValueToRouteData(KeySegment segment, string keyName = "key")
        {
            foreach (var keyValuePair in segment.Keys)
            {
                object       value = keyValuePair.Value;
                ConstantNode node  = value as ConstantNode;
                if (node != null)
                {
                    ODataEnumValue enumValue = node.Value as ODataEnumValue;
                    if (enumValue != null)
                    {
                        value = ODataUriUtils.ConvertToUriLiteral(enumValue, ODataVersion.V4);
                    }
                }

                if (segment.Keys.Count() == 1)
                {
                    RouteData[keyName] = value;
                }
                else
                {
                    RouteData[keyValuePair.Key] = value;
                }
            }
        }
예제 #14
0
 public async Task VisitAsync(ODataPath path)
 {
     NotFound       = false;
     BadRequest     = false;
     Result         = null;
     ResultType     = null;
     PropertySetter = null;
     Index          = 0;
     foreach (var segment in path)
     {
         await(segment switch
         {
             TypeSegment typeSegment => VisitAsync(typeSegment),
             NavigationPropertySegment navigationPropertySegment => VisitAsync(navigationPropertySegment),
             EntitySetSegment entitySetSegment => VisitAsync(entitySetSegment),
             SingletonSegment singletonSegment => VisitAsync(singletonSegment),
             KeySegment keySegment => VisitAsync(keySegment),
             PropertySegment propertySegment => VisitAsync(propertySegment),
             AnnotationSegment annotationSegment => VisitAsync(annotationSegment),
             OperationImportSegment operationImportSegment => VisitAsync(operationImportSegment),
             OperationSegment operationSegment => VisitAsync(operationSegment),
             DynamicPathSegment dynamicPathSegment => VisitAsync(dynamicPathSegment),
             CountSegment countSegment => VisitAsync(countSegment),
             FilterSegment filterSegment => VisitAsync(filterSegment),
             ReferenceSegment referenceSegment => VisitAsync(referenceSegment),
             EachSegment eachSegment => VisitAsync(eachSegment),
             NavigationPropertyLinkSegment navigationPropertyLinkSegment => VisitAsync(navigationPropertyLinkSegment),
             ValueSegment valueSegment => VisitAsync(valueSegment),
             BatchSegment batchSegment => VisitAsync(batchSegment),
             BatchReferenceSegment batchReferenceSegment => VisitAsync(batchReferenceSegment),
             MetadataSegment metadataSegment => VisitAsync(metadataSegment),
             PathTemplateSegment pathTemplateSegment => VisitAsync(pathTemplateSegment),
             _ => throw new NotSupportedException()
         });
예제 #15
0
        public void TypeIsSetCorrectly()
        {
            var        set     = ModelBuildingHelpers.BuildValidEntitySet();
            KeySegment segment = new KeySegment(Key, set.EntityType(), set);

            segment.EdmType.Should().BeSameAs(set.EntityType());
        }
예제 #16
0
        public void CtorKeySegmentTemplate_SetsProperties()
        {
            // 1) Arrange & Act
            IDictionary <string, string> keys1 = new Dictionary <string, string>
            {
                { "customerId", "{key}" }
            };
            KeySegmentTemplate segment1 = new KeySegmentTemplate(keys1, _customerType, _customers);

            // 2) Arrange & Act
            IDictionary <string, object> keys2 = new Dictionary <string, object>
            {
                { "customerId", BuildExpression("{key}") }
            };
            KeySegment         keySegment = new KeySegment(keys2, _customerType, _customers);
            KeySegmentTemplate segment2   = new KeySegmentTemplate(keySegment);

            // Assert
            foreach (var segment in new[] { segment1, segment2 })
            {
                KeyValuePair <string, string> keyMapping = Assert.Single(segment.KeyMappings);
                Assert.Equal("customerId", keyMapping.Key);
                Assert.Equal("key", keyMapping.Value);

                KeyValuePair <string, IEdmProperty> keyProperty = Assert.Single(segment.KeyProperties);
                Assert.Equal("customerId", keyProperty.Key);
                Assert.Equal("customerId", keyProperty.Value.Name);

                Assert.Same(_customers, segment.NavigationSource);
                Assert.Same(_customerType, segment.EntityType);
                Assert.Equal(1, segment.Count);
            }
        }
        public void TryMatchMediaType_DoesnotMatchRequest_ODataEnumValueMediaTypeMappingWithNonRawvalueRequest()
        {
            // Arrange
            IEdmModel      model          = GetEnumModel();
            IEdmEntitySet  enumEntity     = model.EntityContainer.FindEntitySet("EnumEntity");
            IEdmEntityType enumEntityType =
                model.SchemaElements.OfType <IEdmEntityType>().First(e => e.Name == "EnumEntity");

            IEdmStructuralProperty property = enumEntityType.FindProperty("EnumProperty") as IEdmStructuralProperty;

            Assert.NotNull(property); // Guard
            PropertySegment propertySegment = new PropertySegment(property);

            var        keys       = new[] { new KeyValuePair <string, object>("Id", 1) };
            KeySegment keySegment = new KeySegment(keys, enumEntityType, enumEntity);

            ODataPath path = new ODataPath(new EntitySetSegment(enumEntity), keySegment, propertySegment);
            ODataEnumValueMediaTypeMapping mapping = new ODataEnumValueMediaTypeMapping();
            var request = RequestFactory.Create(HttpMethod.Get, "http://localhost/EnumEntity(1)/EnumProperty/");

            request.ODataContext().Path = path;

            // Act
            double mapResult = mapping.TryMatchMediaType(request);

            // Assert
            Assert.Equal(0, mapResult);
        }
        /// <summary>
        /// Translate a KeySegment
        /// </summary>
        /// <param name="segment">the segment to Translate</param>
        /// <returns>Defined by the implementer.</returns>
        public override string Translate(KeySegment segment)
        {
            Debug.Assert(segment != null, "segment != null");
            List <KeyValuePair <string, object> > keys = segment.Keys.ToList();

            StringBuilder builder = new StringBuilder();

            builder.Append("(");

            for (int i = 0; i < keys.Count; i++)
            {
                if (i != 0)
                {
                    builder.Append(",");
                }

                if (keys.Count == 1)
                {
                    builder.Append(ODataUriUtils.ConvertToUriLiteral(keys[i].Value, ODataVersion.V4, DataSourceManager.GetCurrentDataSource().Model));
                }
                else
                {
                    builder.Append(string.Format("{0}={1}", keys[i].Key, ODataUriUtils.ConvertToUriLiteral(keys[i].Value, ODataVersion.V4, DataSourceManager.GetCurrentDataSource().Model)));
                }
            }

            builder.Append(")");

            return(builder.ToString());
        }
예제 #19
0
        /// <inheritdoc/>
        internal static string SelectActionImpl(ODataPath odataPath, IWebApiControllerContext controllerContext, IWebApiActionMap actionMap)
        {
            if (ODataRequestMethod.Post == controllerContext.Request.Method)
            {
                switch (odataPath.PathTemplate)
                {
                case "~/entityset/key/cast/action":
                case "~/entityset/key/action":
                    string actionName = GetAction(odataPath).SelectAction(actionMap, isCollection: false);
                    if (actionName != null)
                    {
                        KeySegment keySegment = (KeySegment)odataPath.Segments[1];
                        controllerContext.AddKeyValueToRouteData(keySegment);
                    }
                    return(actionName);

                case "~/entityset/cast/action":
                case "~/entityset/action":
                    return(GetAction(odataPath).SelectAction(actionMap, isCollection: true));

                case "~/singleton/action":
                case "~/singleton/cast/action":
                    return(GetAction(odataPath).SelectAction(actionMap, isCollection: false));
                }
            }

            return(null);
        }
예제 #20
0
        public override bool TryTranslate(ODataTemplateTranslateContext context)
        {
            if (!context.RouteValues.TryGetValue("navigation", out object navigationNameObj))
            {
                return(false);
            }

            string         navigationName = navigationNameObj as string;
            KeySegment     keySegment     = context.Segments.Last() as KeySegment;
            IEdmEntityType entityType     = keySegment.EdmType as IEdmEntityType;

            IEdmNavigationProperty navigationProperty = entityType.NavigationProperties().FirstOrDefault(n => n.Name == navigationName);

            if (navigationProperty != null)
            {
                var navigationSource = keySegment.NavigationSource;
                IEdmNavigationSource targetNavigationSource = navigationSource.FindNavigationTarget(navigationProperty);

                NavigationPropertySegment seg = new NavigationPropertySegment(navigationProperty, navigationSource);
                context.Segments.Add(seg);
                return(true);
            }

            return(false);
        }
예제 #21
0
        public override string SelectAction(Microsoft.AspNet.OData.Routing.ODataPath odataPath, HttpControllerContext controllerContext, ILookup <string, HttpActionDescriptor> actionMap)
        {
            if (odataPath == null || controllerContext == null || actionMap == null)
            {
                return(null);
            }

            if (odataPath.PathTemplate != "~/entityset/key/navigation" && odataPath.PathTemplate != "~/entityset/key/cast/navigation")
            {
                return(base.SelectAction(odataPath, controllerContext, actionMap));
            }

            if (!controllerContext.ControllerDescriptor.ControllerType.IsSubclassOfRawGeneric(typeof(GenericDataController <>)))
            {
                return(base.SelectAction(odataPath, controllerContext, actionMap));
            }

            var segment = odataPath.Segments[odataPath.Segments.Count - 1] as NavigationPropertySegment;

            if (segment != null)
            {
                if (odataPath.PathTemplate.StartsWith("~/entityset/key", StringComparison.Ordinal))
                {
                    KeySegment keyValueSegment = odataPath.Segments[1] as KeySegment;
                    controllerContext.RouteData.Values[ODataRouteConstants.Key] = keyValueSegment.GenerateKey();
                }
            }
            return(null);
        }
        public void Translate_ReturnsODataKeySegment()
        {
            // Arrange
            EdmModel model = new EdmModel();

            model.AddElement(_customerType);
            model.AddElement(_container);

            IDictionary <string, string> keys = new Dictionary <string, string>
            {
                { "customerId", "{key}" }
            };

            RouteValueDictionary routeValueDictionary = new RouteValueDictionary(new { key = "42" });

            KeySegmentTemplate template = new KeySegmentTemplate(keys, _customerType, _customers);

            HttpContext httpContext = new DefaultHttpContext();
            ODataTemplateTranslateContext context = new ODataTemplateTranslateContext(httpContext, routeValueDictionary, model);

            // Act
            ODataPathSegment actual = template.Translate(context);

            // Assert
            Assert.NotNull(actual);
            KeySegment keySegment = Assert.IsType <KeySegment>(actual);
            var        actualKey  = Assert.Single(keySegment.Keys);

            Assert.Equal("customerId", actualKey.Key);
            Assert.Equal(42, actualKey.Value);
        }
        public void TryMatchMediaTypeWithBinaryRawValueMatchesRequest()
        {
            IEdmModel model = GetBinaryModel();

            IEdmEntitySet  rawValues      = model.EntityContainer.FindEntitySet("RawValue");
            IEdmEntityType rawValueEntity =
                model.SchemaElements.OfType <IEdmEntityType>().First(e => e.Name == "RawValueEntity");

            IEdmStructuralProperty property = rawValueEntity.FindProperty("BinaryProperty") as IEdmStructuralProperty;

            Assert.NotNull(property); // Guard
            PropertySegment propertySegment = new PropertySegment(property);

            var        keys       = new[] { new KeyValuePair <string, object>("Id", 1) };
            KeySegment keySegment = new KeySegment(keys, rawValueEntity, rawValues);

            ODataPath path = new ODataPath(new EntitySetSegment(rawValues), keySegment, propertySegment, new ValueSegment(propertySegment.EdmType));
            ODataBinaryValueMediaTypeMapping mapping = new ODataBinaryValueMediaTypeMapping();
            var request = RequestFactory.Create(HttpMethod.Get, "http://localhost/RawValue(1)/BinaryProperty/$value");

            request.ODataContext().Path = path;

            double mapResult = mapping.TryMatchMediaType(request);

            Assert.Equal(1.0, mapResult);
        }
예제 #24
0
        public void SetIsCopiedFromPreviousSegment()
        {
            var        set     = ModelBuildingHelpers.BuildValidEntitySet();
            KeySegment segment = new KeySegment(Key, set.EntityType(), set);

            Assert.Same(set, segment.NavigationSource);
        }
예제 #25
0
        public void TypeIsSetCorrectly()
        {
            var        set     = ModelBuildingHelpers.BuildValidEntitySet();
            KeySegment segment = new KeySegment(Key, set.EntityType(), set);

            Assert.Same(set.EntityType(), segment.EdmType);
        }
예제 #26
0
        public void ODataPathSegmentToTemplateHandler_Throws_WithoutAlternateKey()
        {
            // Arrange
            EdmModel      model    = new EdmModel();
            EdmEntityType customer = new EdmEntityType("NS", "Customer");

            customer.AddKeys(customer.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32));
            customer.AddStructuralProperty("Code", EdmPrimitiveTypeKind.Int32);
            model.AddElement(customer);

            EdmEntityContainer entityContainer = new EdmEntityContainer("NS", "Default");
            EdmEntitySet       customers       = entityContainer.AddEntitySet("Customers", customer);

            model.AddElement(entityContainer);
            IDictionary <string, object> keys = new Dictionary <string, object>
            {
                { "Code", "{Code}" }
            };

            KeySegment segment = new KeySegment(keys, customer, customers);
            ODataPathSegmentToTemplateHandler handler = new ODataPathSegmentToTemplateHandler(model);

            // Act
            Action test = () => handler.Handle(segment);

            // Assert
            ExceptionAssert.Throws <ODataException>(test, "Cannot find key 'Code' in the 'NS.Customer' type.");
        }
예제 #27
0
        public void KeySetCorrectly()
        {
            var        set     = ModelBuildingHelpers.BuildValidEntitySet();
            KeySegment segment = new KeySegment(Key, set.EntityType(), set);

            segment.Keys.Should().OnlyContain(x => x.Key == "key" && x.Value.As <string>() == "value");
        }
예제 #28
0
        public void ODataPathSegmentToTemplateHandler_Handles_Key()
        {
            // Arrange
            ODataPathSegmentToTemplateHandler handler = new ODataPathSegmentToTemplateHandler(null);

            EdmEntityType customer = new EdmEntityType("NS", "Customer");

            customer.AddKeys(customer.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32));

            EdmEntityContainer           entityContainer = new EdmEntityContainer("NS", "Default");
            EdmEntitySet                 customers       = entityContainer.AddEntitySet("Customers", customer);
            IDictionary <string, object> keys            = new Dictionary <string, object>
            {
                { "Id", "{key}" }
            };

            KeySegment segment = new KeySegment(keys, customer, customers);

            // Act
            handler.Handle(segment);

            // Assert
            ODataSegmentTemplate segmentTemplate = Assert.Single(handler.Templates);

            Assert.IsType <KeySegmentTemplate>(segmentTemplate);
        }
예제 #29
0
        /// <summary>Tries to create a key segment for the given filter if it is non empty.</summary>
        /// <param name="previous">Segment on which to compose.</param>
        /// <param name="previousKeySegment">The parent node's key segment.</param>
        /// <param name="parenthesisExpression">Parenthesis expression of segment.</param>
        /// <param name="keySegment">The key segment that was created if the key was non-empty.</param>
        /// <param name="enableUriTemplateParsing">Whether Uri template parsing is enabled.</param>
        /// <param name="resolver">The resolver to use.</param>
        /// <returns>Whether the key was non-empty.</returns>
        internal static bool TryCreateKeySegmentFromParentheses(ODataPathSegment previous, KeySegment previousKeySegment, string parenthesisExpression, out ODataPathSegment keySegment, bool enableUriTemplateParsing = false, ODataUriResolver resolver = null)
        {
            Debug.Assert(parenthesisExpression != null, "parenthesisExpression != null");
            Debug.Assert(previous != null, "segment!= null");

            if (resolver == null)
            {
                resolver = ODataUriResolver.Default;
            }

            if (previous.SingleResult)
            {
                throw ExceptionUtil.CreateSyntaxError();
            }

            SegmentArgumentParser key;
            if (!SegmentArgumentParser.TryParseKeysFromUri(parenthesisExpression, out key, enableUriTemplateParsing))
            {
                throw ExceptionUtil.CreateSyntaxError();
            }

            // People/NS.Employees() is OK, just like People() is OK
            if (key.IsEmpty)
            {
                keySegment = null;
                return false;
            }

            keySegment = CreateKeySegment(previous, previousKeySegment, key, resolver);
            return true;
        }
예제 #30
0
        public void ODataPathSegmentHandler_Handles_KeySegment()
        {
            // Arrange
            ODataPathSegmentHandler handler = new ODataPathSegmentHandler();

            EdmEntityType customer = new EdmEntityType("NS", "Customer");

            customer.AddKeys(customer.AddStructuralProperty("Id", EdmPrimitiveTypeKind.String));

            EdmEntityContainer           entityContainer = new EdmEntityContainer("NS", "Default");
            EdmEntitySet                 customers       = entityContainer.AddEntitySet("Customers", customer);
            IDictionary <string, object> keys            = new Dictionary <string, object>
            {
                { "Id", "abc" }
            };

            KeySegment segment = new KeySegment(keys, customer, customers);

            // Act
            handler.Handle(segment);

            // Assert
            Assert.Equal("('abc')", handler.PathLiteral);
            Assert.Same(customers, handler.NavigationSource);
        }
        /// <summary>
        /// Translate a KeySegment
        /// </summary>
        /// <param name="segment">the segment to Translate</param>
        /// <returns>Translated the path segment template.</returns>
        public override ODataSegmentTemplate Translate(KeySegment segment)
        {
            if (segment == null)
            {
                throw Error.ArgumentNull(nameof(segment));
            }

            try
            {
                return(new KeySegmentTemplate(segment));
            }
            catch
            {
                if (_model != null)
                {
                    var alternateKeys = _model.ResolveAlternateKeyProperties(segment);
                    if (alternateKeys != null)
                    {
                        return(new KeySegmentTemplate(segment, alternateKeys));
                    }
                }

                throw;
            }
        }
예제 #32
0
 public void EqualityIsCorrect()
 {
     List<KeyValuePair<string, object>> key1 = new List<KeyValuePair<string, object>>() {new KeyValuePair<string, object>("key", "value")};
     List<KeyValuePair<string, object>> key2 = new List<KeyValuePair<string, object>>() { new KeyValuePair<string, object>("key", "value") };
     KeySegment segment1 = new KeySegment(key1, HardCodedTestModel.GetPersonType(), HardCodedTestModel.GetPeopleSet());
     KeySegment segment2 = new KeySegment(key2, HardCodedTestModel.GetPersonType(), HardCodedTestModel.GetPeopleSet());
     segment1.Equals(segment2).Should().BeTrue();
 }
예제 #33
0
 public void InequalityIsCorrect()
 {
     KeySegment segment1 = new KeySegment(new List<KeyValuePair<string, object>>() { new KeyValuePair<string, object>("key", "value1")}, HardCodedTestModel.GetPersonType(), HardCodedTestModel.GetPeopleSet());
     KeySegment segment2 = new KeySegment(new List<KeyValuePair<string, object>>() {new KeyValuePair<string, object>("key", "value1")}, HardCodedTestModel.GetDogType(), HardCodedTestModel.GetDogsSet());
     KeySegment segment3 = new KeySegment(new List<KeyValuePair<string, object>>() { new KeyValuePair<string, object>("key", "value2")}, HardCodedTestModel.GetPersonType(), HardCodedTestModel.GetPeopleSet());
     CountSegment segment4 = CountSegment.Instance;
     segment1.Equals(segment2).Should().BeFalse();
     segment1.Equals(segment3).Should().BeFalse();
     segment1.Equals(segment4).Should().BeFalse();
 }
예제 #34
0
        /// <summary>
        /// Initializes a new instance of the <see cref="KeyValuePathSegment" /> class.
        /// </summary>
        /// <param name="segment">The key segment.</param>
        public KeyValuePathSegment(KeySegment segment)
        {
            if (segment == null)
            {
                throw Error.ArgumentNull("segment");
            }

            Segment = segment;
            Value = segment.TranslateKeyValueToString();
        }
예제 #35
0
        /// <summary>
        /// Tries to handle the current segment as a key property value.
        /// </summary>
        /// <param name="segmentText">The segment text.</param>
        /// <param name="previous">The previous segment.</param>
        /// <param name="previousKeySegment">The parent node's key segment.</param>
        /// <param name="urlConvention">The current url convention for the server.</param>
        /// <param name="keySegment">The key segment that was created if the segment could be interpreted as a key.</param>
        /// <param name="enableUriTemplateParsing">Whether Uri template parsing is enabled.</param>
        /// <param name="resolver">The resolver to use.</param>
        /// <returns>Whether or not the segment was interpreted as a key.</returns>
        internal static bool TryHandleSegmentAsKey(string segmentText, ODataPathSegment previous, KeySegment previousKeySegment, UrlConvention urlConvention, out KeySegment keySegment, bool enableUriTemplateParsing = false, ODataUriResolver resolver = null)
        {
            Debug.Assert(previous != null, "previous != null");
            Debug.Assert(urlConvention != null, "urlConvention != null");

            if (resolver == null)
            {
                resolver = ODataUriResolver.Default;
            }

            keySegment = null;

            // If the current convention is not keys-as-segments, then this does not apply.
            if (!urlConvention.GenerateKeyAsSegment)
            {
                return false;
            }

            // Keys only apply to collections, so if the prior segment is already a singleton, do not treat this segment as a key.
            if (previous.SingleResult)
            {
                return false;
            }

            // System segments (ie '$count') are never keys.
            if (IsSystemSegment(segmentText))
            {
                return false;
            }

            // If the previous type is not an entity collection type
            // TODO: collapse this and SingleResult.
            IEdmEntityType targetEntityType;
            if (previous.TargetEdmType == null || !previous.TargetEdmType.IsEntityOrEntityCollectionType(out targetEntityType))
            {
                return false;
            }

            // Previously KeyAsSegment only allows single key, but we can also leverage related key finder to auto fill
            // missed key value from referential constraint information, which would be done in CreateKeySegment.
            // CreateKeySegment method will check whether key properties are missing after taking in related key values.
            keySegment = CreateKeySegment(previous, previousKeySegment, SegmentArgumentParser.FromSegment(segmentText, enableUriTemplateParsing), resolver);

            return true;
        }
        public void Translate_KeySegment_To_KeyValuePathSegment_Works()
        {
            // Arrange
            IEdmEntityType entityType = _model.FindDeclaredType("System.Web.OData.Routing.RoutingCustomer") as IEdmEntityType;
            IEdmEntitySet entityset = _model.FindDeclaredEntitySet("RoutingCustomers");
            KeySegment segment = new KeySegment(new[] { new KeyValuePair<string, object>("ID", 42) }, entityType, entityset);

            // Act
            IEnumerable<ODataPathSegment> segments = _translator.Translate(segment);

            // Assert
            ODataPathSegment pathSegment = Assert.Single(segments);
            KeyValuePathSegment keyValuePathSegment = Assert.IsType<KeyValuePathSegment>(pathSegment);
            Assert.Equal("42", keyValuePathSegment.Value);
        }
예제 #37
0
        private static IReadOnlyDictionary<string, object> GetPathKeyValues(
            KeySegment keySegment)
        {
            var result = new Dictionary<string, object>();

            // TODO GitHubIssue#42 : Improve key parsing logic
            // this parsing implementation does not allow key values to contain commas
            // Depending on the WebAPI to make KeyValuePathSegment.Values collection public
            // (or have the parsing logic public).
            var keyValuePairs = keySegment.Keys;

            foreach (var keyValuePair in keyValuePairs)
            {
                result.Add(keyValuePair.Key, keyValuePair.Value);
            }

            return result;
        }
예제 #38
0
 /// <summary>
 /// Handle a KeySegment
 /// </summary>
 /// <param name="segment">the segment to Handle</param>
 public virtual void Handle(KeySegment segment)
 {
     throw new NotImplementedException();
 }
예제 #39
0
 public void SetIsCopiedFromPreviousSegment()
 {
     var set = ModelBuildingHelpers.BuildValidEntitySet();
     KeySegment segment = new KeySegment(Key, set.EntityType(), set);
     segment.NavigationSource.Should().BeSameAs(set);
 }
예제 #40
0
        private static KeySegment BuildKeySegment(IEdmEntityType entityType, IEdmEntitySetBase entitySet, object target)
        {
            if (entityType == null)
            {
                throw new ArgumentNullException("entityType");
            }

            if (entitySet == null)
            {
                throw new ArgumentNullException("entitySet");
            }

            if (target == null)
            {
                throw new ArgumentNullException("target");
            }

            KeySegment keySegment = new KeySegment(
                entityType.Key().Select(
                    (key) =>
                    {
                        var keyValue = target.GetType().GetProperty(key.Name).GetValue(target, null);
                        return new KeyValuePair<string, object>(key.Name, keyValue);
                    }),
                entityType,
                entitySet);

            return keySegment;
        }
예제 #41
0
        /// <summary>
        /// Append the key segment in the end of ODataPath, the method does not modify current ODataPath instance,
        /// it returns a new ODataPath without ending type segment.
        /// If last segment is type cast, the key would be appended before type cast segment.
        /// </summary>
        /// <param name="path">Path to perform the computation on.</param>
        /// <param name="keys">The set of key property names and the values to be used in searching for the given item.</param>
        /// <param name="edmType">The type of the item this key returns.</param>
        /// <param name="navigationSource">The navigation source that this key is used to search.</param>
        /// <returns>The ODataPath with key segment appended</returns>
        public static ODataPath AppendKeySegment(this ODataPath path, IEnumerable<KeyValuePair<string, object>> keys, IEdmEntityType edmType, IEdmNavigationSource navigationSource)
        {
            var handler = new SplitEndingSegmentOfTypeHandler<TypeSegment>();
            path.WalkWith(handler);
            KeySegment keySegment = new KeySegment(keys, edmType, navigationSource);
            ODataPath newPath = handler.FirstPart;
            newPath.Add(keySegment);
            foreach (var segment in handler.LastPart)
            {
                newPath.Add(segment);
            }

            return newPath;
        }
예제 #42
0
        /// <summary>
        /// Parses the key properties based on the segment's target type, then creates a new segment for the key.
        /// </summary>
        /// <param name="segment">The segment to apply the key to.</param>
        /// <param name="previousKeySegment">The parent node's key segment.</param>
        /// <param name="key">The key to apply.</param>
        /// <param name="resolver">The resolver to use.</param>
        /// <returns>The newly created key segment.</returns>
        private static KeySegment CreateKeySegment(ODataPathSegment segment, KeySegment previousKeySegment, SegmentArgumentParser key, ODataUriResolver resolver)
        {
            Debug.Assert(segment != null, "segment != null");
            Debug.Assert(key != null && !key.IsEmpty, "key != null && !key.IsEmpty");
            Debug.Assert(segment.SingleResult == false, "segment.SingleResult == false");

            IEdmEntityType targetEntityType = null;
            if (!(segment.TargetEdmType != null && segment.TargetEdmType.IsEntityOrEntityCollectionType(out targetEntityType)))
            {
                throw ExceptionUtil.CreateSyntaxError();
            }

            Debug.Assert(targetEntityType != null, "targetEntityType != null");

            // Make sure the keys specified in the uri matches with the number of keys in the metadata
            var keyProperties = targetEntityType.Key().ToList();
            if (keyProperties.Count != key.ValueCount)
            {
                NavigationPropertySegment currentNavPropSegment = segment as NavigationPropertySegment;
                if (currentNavPropSegment != null)
                {
                    key = KeyFinder.FindAndUseKeysFromRelatedSegment(key, keyProperties, currentNavPropSegment.NavigationProperty, previousKeySegment);
                }

                // if we still didn't find any keys, then throw an error.
                if (keyProperties.Count != key.ValueCount && resolver.GetType() == typeof(ODataUriResolver))
                {
                    throw ExceptionUtil.CreateBadRequestError(ErrorStrings.BadRequest_KeyCountMismatch(targetEntityType.FullName()));
                }
            }

            if (!key.AreValuesNamed && key.ValueCount > 1 && resolver.GetType() == typeof(ODataUriResolver))
            {
                throw ExceptionUtil.CreateBadRequestError(ErrorStrings.RequestUriProcessor_KeysMustBeNamed);
            }

            IEnumerable<KeyValuePair<string, object>> keyPairs;
            if (!key.TryConvertValues(targetEntityType, out keyPairs, resolver))
            {
                throw ExceptionUtil.CreateSyntaxError();
            }

            IEdmEntityType entityType;
            bool isEntity = segment.TargetEdmType.IsEntityOrEntityCollectionType(out entityType);
            Debug.Assert(isEntity, "Key target type should be an entity type.");

            var keySegment = new KeySegment(keyPairs, entityType, segment.TargetEdmNavigationSource);
            keySegment.CopyValuesFrom(segment);
            keySegment.SingleResult = true;

            return keySegment;
        }
예제 #43
0
        /// <summary>
        /// Find any related keys from the parent key segment, if it exists, and add them to the raw key values that
        /// we already have from the uri.
        /// </summary>
        /// <param name="rawKeyValuesFromUri">The raw key values as we've parsed them from the uri.</param>
        /// <param name="targetEntityKeyProperties">The list of key properties on the target entity.</param>
        /// <param name="currentNavigationProperty">The current navigation property that we're trying to follow using the raw key values</param>
        /// <param name="keySegmentOfParentEntity">The key segment of the parent entity in this path, if it exists. Null otherwise</param>
        /// <returns>A new SegmentArgumentParser with any keys that were found added to its list of NamedValues.</returns>
        /// <throws>Thorws if the input currentNavigationProperty is null.</throws>
        public static SegmentArgumentParser FindAndUseKeysFromRelatedSegment(SegmentArgumentParser rawKeyValuesFromUri, IEnumerable<IEdmStructuralProperty> targetEntityKeyProperties, IEdmNavigationProperty currentNavigationProperty, KeySegment keySegmentOfParentEntity)
        {
            ExceptionUtils.CheckArgumentNotNull(currentNavigationProperty, "currentNavigationProperty");
            ExceptionUtils.CheckArgumentNotNull(rawKeyValuesFromUri, "rawKeyValuesFromUri");

            ReadOnlyCollection<IEdmStructuralProperty> targetKeyPropertyList = targetEntityKeyProperties != null ? new ReadOnlyCollection<IEdmStructuralProperty>(targetEntityKeyProperties.ToList()) : new ReadOnlyCollection<IEdmStructuralProperty>(new List<IEdmStructuralProperty>());

            // should only get here if the number of raw parameters from the uri is different than the number of key properties for the target entity.
            Debug.Assert(rawKeyValuesFromUri.ValueCount < targetKeyPropertyList.Count(), "rawKeyValuesFromUri.ValueCount < targetEntityKeyProperties.Count()");

            // if the raw key from the uri has positional values, there must be only one of them
            // its important to cache this value here because we'll change it when we add new 
            // named values below (the implementation of AreValuesNamed is just namedValues !=null)
            bool hasPositionalValues = !rawKeyValuesFromUri.AreValuesNamed;
            if (hasPositionalValues && rawKeyValuesFromUri.ValueCount > 1)
            {
                return rawKeyValuesFromUri;
            }

            if (keySegmentOfParentEntity == null)
            {
                return rawKeyValuesFromUri;
            }

            // TODO: p2 merge the below 2 pieces of codes
            // find out if any target entity key properties have referential constraints that link them to the previous rawKeyValuesFromUri.
            List<EdmReferentialConstraintPropertyPair> keysFromReferentialIntegrityConstraint = ExtractMatchingPropertyPairsFromNavProp(currentNavigationProperty, targetKeyPropertyList).ToList();

            foreach (EdmReferentialConstraintPropertyPair keyFromReferentialIntegrityConstraint in keysFromReferentialIntegrityConstraint)
            {
                KeyValuePair<string, object> valueFromParent = keySegmentOfParentEntity.Keys.SingleOrDefault(x => x.Key == keyFromReferentialIntegrityConstraint.DependentProperty.Name);
                if (valueFromParent.Key != null)
                {
                    // if the key from the referential integrity constraint is one of the target key properties
                    // and that key property isn't already populated in the raw key values from the uri, then
                    // we set that value to the value from the parent key segment.
                    if (targetKeyPropertyList.Any(x => x.Name == keyFromReferentialIntegrityConstraint.PrincipalProperty.Name))
                    {
                        rawKeyValuesFromUri.AddNamedValue(
                            keyFromReferentialIntegrityConstraint.PrincipalProperty.Name,
                            valueFromParent.Value.ToString());
                    }
                }
            }

            // also need to look to see if any nav props exist in the target set that refer back to this same set, which might have 
            // referential constraints also.
            keysFromReferentialIntegrityConstraint.Clear();
            IEdmNavigationProperty reverseNavProp = currentNavigationProperty.Partner;
            if (reverseNavProp != null)
            {
                keysFromReferentialIntegrityConstraint.AddRange(ExtractMatchingPropertyPairsFromReversedNavProp(reverseNavProp, targetKeyPropertyList));
            }

            foreach (EdmReferentialConstraintPropertyPair keyFromReferentialIntegrityConstraint in keysFromReferentialIntegrityConstraint)
            {
                KeyValuePair<string, object> valueFromParent = keySegmentOfParentEntity.Keys.SingleOrDefault(x => x.Key == keyFromReferentialIntegrityConstraint.PrincipalProperty.Name);
                if (valueFromParent.Key != null)
                {
                    // if the key from the referential integrity constraint is one of the target key properties
                    // and that key property isn't already populated in the raw key values from the uri, then
                    // we set that value to the value from the parent key segment.
                    if (targetKeyPropertyList.Any(x => x.Name == keyFromReferentialIntegrityConstraint.DependentProperty.Name))
                    {
                        rawKeyValuesFromUri.AddNamedValue(
                            keyFromReferentialIntegrityConstraint.DependentProperty.Name,
                            valueFromParent.Value.ToString());
                    }
                }
            }

            // if we had a positional value before, then we need to add that value as a new named value.
            // the name that we choose will be the only value from the target entity key properties
            // that isn't already set in the NamedValues list.
            if (hasPositionalValues)
            {
                if (rawKeyValuesFromUri.NamedValues != null)
                {
                    List<IEdmStructuralProperty> unassignedProperties = targetKeyPropertyList.Where(x => !rawKeyValuesFromUri.NamedValues.ContainsKey(x.Name)).ToList();

                    if (unassignedProperties.Count == 1)
                    {
                        rawKeyValuesFromUri.AddNamedValue(unassignedProperties[0].Name, rawKeyValuesFromUri.PositionalValues[0]);
                    }
                    else
                    {
                        return rawKeyValuesFromUri;
                    }

                    // clear out the positional value so that we keep a consistent state in the 
                    // raw keys from uri.
                    rawKeyValuesFromUri.PositionalValues.Clear();
                }
                else
                {
                    return rawKeyValuesFromUri;
                }
            }

            return rawKeyValuesFromUri;
        }
예제 #44
0
        /// <summary>
        /// Build canonical URI base on current query target
        /// </summary>
        /// <param name="rootUri">The root URI</param>
        /// <param name="keySegment">The additional key segment of current target.</param>
        /// <returns>The canonical URI</returns>
        public Uri BuildCanonicalUri(Uri rootUri, KeySegment keySegment)
        {
            List<ODataPathSegment> segments = new List<ODataPathSegment>(this.canonicalSegments);

            if (keySegment != null && this.IsEntitySet)
            {
                if (segments.Last() is TypeSegment)
                {
                    segments.Insert(segments.Count - 1, keySegment);
                }
                else
                {
                    segments.Add(keySegment);
                }
            }

            ODataPath path = new ODataPath(segments);
            return new Uri(rootUri, string.Concat(path.WalkWith(PathSegmentToResourcePathTranslator.Instance)).TrimStart('/'));
        }
예제 #45
0
 public void KeySetCorrectly()
 {
     var set = ModelBuildingHelpers.BuildValidEntitySet();
     KeySegment segment = new KeySegment(Key, set.EntityType(), set);
     segment.Keys.Should().OnlyContain(x => x.Key == "key" && x.Value.As<string>() == "value");
 }
예제 #46
0
 public void TypeIsSetCorrectly()
 {
     var set = ModelBuildingHelpers.BuildValidEntitySet();
     KeySegment segment = new KeySegment(Key, set.EntityType(), set);
     segment.EdmType.Should().BeSameAs(set.EntityType());
 }
예제 #47
0
        /// <summary>Selects a single resource by key values.</summary>
        /// <param name="queryExpression">Base query for resources</param>
        /// <param name="resourceType">resource type whose keys are specified</param>
        /// <param name="key">Key values for the given resource type.</param>
        /// <returns>A new query that selects the single resource that matches the specified key values.</returns>
        private static Expression SelectResourceByKey(Expression queryExpression, ResourceType resourceType, KeySegment key)
        {
            Debug.Assert(queryExpression != null, "queryExpression != null");
            Debug.Assert(key != null, "key != null");
            
            List<KeyValuePair<string, object>> keyValues = key.Keys.ToList();
            Debug.Assert(keyValues.Count != 0, "keyValues.Count != 0");
            Debug.Assert(resourceType.KeyProperties.Count == keyValues.Count, "resourceType.KeyProperties.Count == keyValues.Count");

            for (int i = 0; i < resourceType.KeyProperties.Count; i++)
            {
                ResourceProperty keyProperty = resourceType.KeyProperties[i];
                Debug.Assert(keyProperty.IsOfKind(ResourcePropertyKind.Key), "keyProperty.IsOfKind(ResourcePropertyKind.Key)");

                object keyValue;
                if (keyValues.Count == 0)
                {
                    keyValue = keyValues[0].Value;
                }
                else
                {
                    keyValue = keyValues.Single(v => v.Key == keyProperty.Name).Value;    
                }
                
                var binaryValue = keyValue as byte[];
                if (binaryValue != null && keyProperty.Type == typeof(System.Data.Linq.Binary))
                {
                    keyValue = new System.Data.Linq.Binary(binaryValue);
                }

                var stringValue = keyValue as string;
                if (stringValue != null && keyProperty.Type == typeof(XElement))
                {
                    keyValue = XElement.Parse(stringValue);
                }

                if (keyProperty.Type == typeof(DateTime))
                {
                    Debug.Assert(keyValue != null && keyValue is DateTimeOffset, "For DateTime properties, the value must be read as DateTimeOffset");
                    keyValue = WebUtil.ConvertDateTimeOffsetToDateTime((DateTimeOffset)keyValue);
                }

                ParameterExpression parameter = Expression.Parameter(queryExpression.ElementType(), "element");
                Expression e;
                if (keyProperty.CanReflectOnInstanceTypeProperty)
                {
                    e = Expression.Property(parameter, keyProperty.Name);
                }
                else
                {
                    e = Expression.Call(null /*instance*/, DataServiceProviderMethods.GetValueMethodInfo, parameter, Expression.Constant(keyProperty));
                    e = Expression.Convert(e, keyProperty.Type);
                }

                BinaryExpression body = Expression.Equal(e, Expression.Constant(keyValue));
                LambdaExpression predicate = Expression.Lambda(body, parameter);
                queryExpression = queryExpression.QueryableWhere(predicate);
            }

            return queryExpression;
        }
예제 #48
0
        public override void Handle(KeySegment segment)
        {
            this.ThrowIfResolved();

            this.Type = segment.EdmType;
            this.ElementType = this.GetElementType(this.Type);

            this.PushParentSegment();
            this.childSegments.Add(segment);

            this.canonicalSegments.Add(segment);
        }