public void ParseTypeCastOnNavigationPropertyWithDerivedTypeConstraintAnnotationWorks(bool isInLine) { string annotation = @"<Annotation Term=""Org.OData.Validation.V1.DerivedTypeConstraint"" >" + "<Collection>" + "<String>NS.VipCustomer</String>" + "</Collection>" + "</Annotation>"; IEdmModel edmModel = GetNavigationPropertyEdmModel(annotation, isInLine); IEdmEntityType customer = edmModel.SchemaElements.OfType <IEdmEntityType>().First(c => c.Name == "Customer"); IEdmEntityType vipCustomer = edmModel.SchemaElements.OfType <IEdmEntityType>().First(c => c.Name == "VipCustomer"); IEdmType collectionCustomerType = new EdmCollectionType(new EdmEntityTypeReference(customer, true)); int index = 1; foreach (string segment in new[] { "DirectReport", "SubCustomers" }) { IEdmType actualType = index == 1 ? customer : collectionCustomerType; // verify the positive type cast on itself ODataPathParser pathParser = new ODataPathParser(new ODataUriParserConfiguration(edmModel)); var path = pathParser.ParsePath(new[] { "Customers(1)", segment, "NS.Customer" }); path[3].ShouldBeTypeSegment(actualType, customer); // verify the positive type cast path = pathParser.ParsePath(new[] { "Customers(1)", segment, "NS.VipCustomer" }); path[3].ShouldBeTypeSegment(actualType, vipCustomer); // verify the negative type cast Action parsePath = () => pathParser.ParsePath(new[] { "Customers(1)", segment, "NS.NormalCustomer" }); parsePath.ShouldThrow <ODataException>().WithMessage(ErrorStrings.PathParser_TypeCastOnlyAllowedInDerivedTypeConstraint("NS.NormalCustomer", "navigation property", segment)); index++; } }
public void SelectAction_WithCast_Returns_ExpectedActionName(string method, string expected) { // Arrange CustomersModelWithInheritance model = new CustomersModelWithInheritance(); IEdmCollectionType collection = new EdmCollectionType(new EdmEntityTypeReference(model.SpecialCustomer, isNullable: false)); ODataPath odataPath = new ODataPath(new EntitySetSegment(model.Customers), new TypeSegment(collection, model.Customers)); var controllerContext = new HttpControllerContext() { Request = new HttpRequestMessage(new HttpMethod(method), "http://localhost/"), RouteData = new HttpRouteData(new HttpRoute()) }; ILookup <string, HttpActionDescriptor> actionMap = new HttpActionDescriptor[1].ToLookup(desc => expected); // Act string actionName = new EntitySetRoutingConvention().SelectAction(odataPath, controllerContext, actionMap); // Assert Assert.Equal(expected, actionName); }
public void ParseTypeCastOnPropertyWithDerivedTypeConstraintAnnotationWorks(bool isInLine) { string annotation = @"<Annotation Term=""Org.OData.Validation.V1.DerivedTypeConstraint"" >" + "<Collection>" + "<String>NS.UsAddress</String>" + "</Collection>" + "</Annotation>"; IEdmModel edmModel = GetPropertyEdmModel(annotation, isInLine); IEdmComplexType address = edmModel.SchemaElements.OfType <IEdmComplexType>().First(c => c.Name == "Address"); IEdmComplexType usAddress = edmModel.SchemaElements.OfType <IEdmComplexType>().First(c => c.Name == "UsAddress"); IEdmType collectionAddressType = new EdmCollectionType(new EdmComplexTypeReference(address, true)); int index = 1; foreach (string segment in new[] { "Address", "Locations" }) { IEdmType actualType = index == 1 ? address : collectionAddressType; // verify the positive type cast on itself ODataPathParser pathParser = new ODataPathParser(new ODataUriParserConfiguration(edmModel)); var path = pathParser.ParsePath(new[] { "Customers(1)", segment, "NS.Address" }); path[3].ShouldBeTypeSegment(actualType, address); // verify the positive type cast path = pathParser.ParsePath(new[] { "Customers(1)", segment, "NS.UsAddress" }); path[3].ShouldBeTypeSegment(actualType, usAddress); // verify the negative type cast Action parsePath = () => pathParser.ParsePath(new[] { "Customers(1)", segment, "NS.CnAddress" }); parsePath.ShouldThrow <ODataException>().WithMessage(ErrorStrings.PathParser_TypeCastOnlyAllowedInDerivedTypeConstraint("NS.CnAddress", "property", segment)); index++; } }
public void ParseTypeCastOnNavigationPropertyWithoutDerivedTypeConstraintAnnotationWorks(string propertyName, string key, string typeCast) { IEdmModel edmModel = GetNavigationPropertyEdmModel(""); ODataPathParser pathParser = new ODataPathParser(new ODataUriParserConfiguration(edmModel)); IEdmEntityType customer = edmModel.SchemaElements.OfType <IEdmEntityType>().First(c => c.Name == "Customer"); IEdmNavigationProperty property = customer.NavigationProperties().First(c => c.Name == propertyName); IEdmType collectionCustomerType = new EdmCollectionType(new EdmEntityTypeReference(customer, true)); IEdmType castType = edmModel.FindDeclaredType(typeCast); Assert.NotNull(castType); int index = key != null ? 4 : 3; IEdmType actualType = propertyName == "SubCustomers" && key == null ? collectionCustomerType : customer; IEdmType expectedType = propertyName == "SubCustomers" && key == null ? new EdmCollectionType(new EdmEntityTypeReference(castType as IEdmEntityType, true)) : castType; // ~/Customers(1)/{propertyName}/{typeCast} var path = pathParser.ParsePath(new[] { "Customers(1)", propertyName + key, typeCast }); path[index].ShouldBeTypeSegment(expectedType, actualType); }
public UriParameterReaderIntegrationTests() { model = new EdmModel(); cityT = new EdmComplexType(ns, "City"); cityT.AddStructuralProperty("CityName", EdmPrimitiveTypeKind.String, false); cityT.AddStructuralProperty("AreaCode", EdmPrimitiveTypeKind.String, true); model.AddElement(cityT); addressT = new EdmComplexType(ns, "Address"); addressT.AddStructuralProperty("City", new EdmComplexTypeReference(cityT, true)); model.AddElement(addressT); companyAddressT = new EdmComplexType(ns, "CompanyAddress", addressT, false); companyAddressT.AddStructuralProperty("CompanyName", EdmPrimitiveTypeKind.String); model.AddElement(companyAddressT); otherInfoT = new EdmComplexType(ns, "OtherInfo", null, false, true); otherInfoT.AddStructuralProperty("Hight", EdmPrimitiveTypeKind.Int32); model.AddElement(otherInfoT); personT = new EdmEntityType("NS", "Person", null, false, true); var Id = personT.AddStructuralProperty("Id", EdmCoreModel.Instance.GetInt32(false)); personT.AddKeys(Id); personT.AddStructuralProperty("Address", new EdmComplexTypeReference(addressT, false)); personT.AddStructuralProperty("CompanyAddress", new EdmComplexTypeReference(companyAddressT, true)); billingAddressesT = new EdmCollectionType(new EdmComplexTypeReference(addressT, false)); personT.AddStructuralProperty("BillingAddresses", new EdmCollectionTypeReference(billingAddressesT)); model.AddElement(personT); EdmEntityContainer container = new EdmEntityContainer(ns, "Container"); peopleSet = new EdmEntitySet(container, "people", personT); model.AddElement(container); }
public CustomersModelWithInheritance() { EdmModel model = new EdmModel(); // Enum type simpleEnum EdmEnumType simpleEnum = new EdmEnumType("NS", "SimpleEnum"); simpleEnum.AddMember(new EdmEnumMember(simpleEnum, "First", new EdmEnumMemberValue(0))); simpleEnum.AddMember(new EdmEnumMember(simpleEnum, "Second", new EdmEnumMemberValue(1))); simpleEnum.AddMember(new EdmEnumMember(simpleEnum, "Third", new EdmEnumMemberValue(2))); model.AddElement(simpleEnum); // complex type address EdmComplexType address = new EdmComplexType("NS", "Address"); address.AddStructuralProperty("Street", EdmPrimitiveTypeKind.String); address.AddStructuralProperty("City", EdmPrimitiveTypeKind.String); address.AddStructuralProperty("State", EdmPrimitiveTypeKind.String); address.AddStructuralProperty("ZipCode", EdmPrimitiveTypeKind.String); address.AddStructuralProperty("CountryOrRegion", EdmPrimitiveTypeKind.String); model.AddElement(address); // open complex type "Account" EdmComplexType account = new EdmComplexType("NS", "Account", null, false, true); account.AddStructuralProperty("Bank", EdmPrimitiveTypeKind.String); account.AddStructuralProperty("CardNum", EdmPrimitiveTypeKind.Int64); account.AddStructuralProperty("BankAddress", new EdmComplexTypeReference(address, isNullable: true)); model.AddElement(account); EdmComplexType specialAccount = new EdmComplexType("NS", "SpecialAccount", account, false, true); specialAccount.AddStructuralProperty("SpecialCard", EdmPrimitiveTypeKind.String); model.AddElement(specialAccount); // entity type customer EdmEntityType customer = new EdmEntityType("NS", "Customer"); customer.AddKeys(customer.AddStructuralProperty("ID", EdmPrimitiveTypeKind.Int32)); IEdmProperty customerName = customer.AddStructuralProperty("Name", EdmPrimitiveTypeKind.String); customer.AddStructuralProperty("SimpleEnum", simpleEnum.ToEdmTypeReference(isNullable: false)); customer.AddStructuralProperty("Address", new EdmComplexTypeReference(address, isNullable: true)); customer.AddStructuralProperty("Account", new EdmComplexTypeReference(account, isNullable: true)); IEdmTypeReference primitiveTypeReference = EdmCoreModel.Instance.GetPrimitive( EdmPrimitiveTypeKind.String, isNullable: true); var city = customer.AddStructuralProperty( "City", primitiveTypeReference, defaultValue: null); model.AddElement(customer); // derived entity type special customer EdmEntityType specialCustomer = new EdmEntityType("NS", "SpecialCustomer", customer); specialCustomer.AddStructuralProperty("SpecialCustomerProperty", EdmPrimitiveTypeKind.Guid); specialCustomer.AddStructuralProperty("SpecialAddress", new EdmComplexTypeReference(address, isNullable: true)); model.AddElement(specialCustomer); // entity type order (open entity type) EdmEntityType order = new EdmEntityType("NS", "Order", null, false, true); // EdmEntityType order = new EdmEntityType("NS", "Order"); order.AddKeys(order.AddStructuralProperty("ID", EdmPrimitiveTypeKind.Int32)); order.AddStructuralProperty("City", EdmPrimitiveTypeKind.String); order.AddStructuralProperty("Amount", EdmPrimitiveTypeKind.Int32); model.AddElement(order); // derived entity type special order EdmEntityType specialOrder = new EdmEntityType("NS", "SpecialOrder", order, false, true); specialOrder.AddStructuralProperty("SpecialOrderProperty", EdmPrimitiveTypeKind.Guid); model.AddElement(specialOrder); // test entity EdmEntityType testEntity = new EdmEntityType("Microsoft.AspNet.OData.Test.Query.Expressions", "TestEntity"); testEntity.AddStructuralProperty("SampleProperty", EdmPrimitiveTypeKind.Binary); model.AddElement(testEntity); // containment // my order EdmEntityType myOrder = new EdmEntityType("NS", "MyOrder"); myOrder.AddKeys(myOrder.AddStructuralProperty("ID", EdmPrimitiveTypeKind.Int32)); myOrder.AddStructuralProperty("Name", EdmPrimitiveTypeKind.String); model.AddElement(myOrder); // order line EdmEntityType orderLine = new EdmEntityType("NS", "OrderLine"); orderLine.AddKeys(orderLine.AddStructuralProperty("ID", EdmPrimitiveTypeKind.Int32)); orderLine.AddStructuralProperty("Name", EdmPrimitiveTypeKind.String); model.AddElement(orderLine); EdmNavigationProperty orderLinesNavProp = myOrder.AddUnidirectionalNavigation( new EdmNavigationPropertyInfo { Name = "OrderLines", TargetMultiplicity = EdmMultiplicity.Many, Target = orderLine, ContainsTarget = true, }); EdmNavigationProperty nonContainedOrderLinesNavProp = myOrder.AddUnidirectionalNavigation( new EdmNavigationPropertyInfo { Name = "NonContainedOrderLines", TargetMultiplicity = EdmMultiplicity.Many, Target = orderLine, ContainsTarget = false, }); EdmAction tag = new EdmAction("NS", "tag", returnType: null, isBound: true, entitySetPathExpression: null); tag.AddParameter("entity", new EdmEntityTypeReference(orderLine, false)); model.AddElement(tag); // entity sets EdmEntityContainer container = new EdmEntityContainer("NS", "ModelWithInheritance"); model.AddElement(container); EdmEntitySet customers = container.AddEntitySet("Customers", customer); EdmEntitySet orders = container.AddEntitySet("Orders", order); EdmEntitySet myOrders = container.AddEntitySet("MyOrders", myOrder); // singletons EdmSingleton vipCustomer = container.AddSingleton("VipCustomer", customer); EdmSingleton mary = container.AddSingleton("Mary", customer); EdmSingleton rootOrder = container.AddSingleton("RootOrder", order); // annotations model.SetOptimisticConcurrencyAnnotation(customers, new[] { city }); // containment IEdmContainedEntitySet orderLines = (IEdmContainedEntitySet)myOrders.FindNavigationTarget(orderLinesNavProp); // no-containment IEdmNavigationSource nonContainedOrderLines = myOrders.FindNavigationTarget(nonContainedOrderLinesNavProp); // actions EdmAction upgrade = new EdmAction("NS", "upgrade", returnType: null, isBound: true, entitySetPathExpression: null); upgrade.AddParameter("entity", new EdmEntityTypeReference(customer, false)); model.AddElement(upgrade); EdmAction specialUpgrade = new EdmAction("NS", "specialUpgrade", returnType: null, isBound: true, entitySetPathExpression: null); specialUpgrade.AddParameter("entity", new EdmEntityTypeReference(specialCustomer, false)); model.AddElement(specialUpgrade); // actions bound to collection EdmAction upgradeAll = new EdmAction("NS", "UpgradeAll", returnType: null, isBound: true, entitySetPathExpression: null); upgradeAll.AddParameter("entityset", new EdmCollectionTypeReference(new EdmCollectionType(new EdmEntityTypeReference(customer, false)))); model.AddElement(upgradeAll); EdmAction upgradeSpecialAll = new EdmAction("NS", "UpgradeSpecialAll", returnType: null, isBound: true, entitySetPathExpression: null); upgradeSpecialAll.AddParameter("entityset", new EdmCollectionTypeReference(new EdmCollectionType(new EdmEntityTypeReference(specialCustomer, false)))); model.AddElement(upgradeSpecialAll); // functions IEdmTypeReference returnType = EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.Boolean, isNullable: false); IEdmTypeReference stringType = EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.String, isNullable: false); IEdmTypeReference intType = EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.Int32, isNullable: false); EdmFunction IsUpgraded = new EdmFunction( "NS", "IsUpgraded", returnType, isBound: true, entitySetPathExpression: null, isComposable: false); IsUpgraded.AddParameter("entity", new EdmEntityTypeReference(customer, false)); model.AddElement(IsUpgraded); EdmFunction orderByCityAndAmount = new EdmFunction( "NS", "OrderByCityAndAmount", stringType, isBound: true, entitySetPathExpression: null, isComposable: false); orderByCityAndAmount.AddParameter("entity", new EdmEntityTypeReference(customer, false)); orderByCityAndAmount.AddParameter("city", stringType); orderByCityAndAmount.AddParameter("amount", intType); model.AddElement(orderByCityAndAmount); EdmFunction getOrders = new EdmFunction( "NS", "GetOrders", EdmCoreModel.GetCollection(order.ToEdmTypeReference(false)), isBound: true, entitySetPathExpression: null, isComposable: true); getOrders.AddParameter("entity", new EdmEntityTypeReference(customer, false)); getOrders.AddParameter("parameter", intType); model.AddElement(getOrders); EdmFunction IsSpecialUpgraded = new EdmFunction( "NS", "IsSpecialUpgraded", returnType, isBound: true, entitySetPathExpression: null, isComposable: false); IsSpecialUpgraded.AddParameter("entity", new EdmEntityTypeReference(specialCustomer, false)); model.AddElement(IsSpecialUpgraded); EdmFunction getSalary = new EdmFunction( "NS", "GetSalary", stringType, isBound: true, entitySetPathExpression: null, isComposable: false); getSalary.AddParameter("entity", new EdmEntityTypeReference(customer, false)); model.AddElement(getSalary); getSalary = new EdmFunction( "NS", "GetSalary", stringType, isBound: true, entitySetPathExpression: null, isComposable: false); getSalary.AddParameter("entity", new EdmEntityTypeReference(specialCustomer, false)); model.AddElement(getSalary); EdmFunction IsAnyUpgraded = new EdmFunction( "NS", "IsAnyUpgraded", returnType, isBound: true, entitySetPathExpression: null, isComposable: false); EdmCollectionType edmCollectionType = new EdmCollectionType(new EdmEntityTypeReference(customer, false)); IsAnyUpgraded.AddParameter("entityset", new EdmCollectionTypeReference(edmCollectionType)); model.AddElement(IsAnyUpgraded); EdmFunction isCustomerUpgradedWithParam = new EdmFunction( "NS", "IsUpgradedWithParam", returnType, isBound: true, entitySetPathExpression: null, isComposable: false); isCustomerUpgradedWithParam.AddParameter("entity", new EdmEntityTypeReference(customer, false)); isCustomerUpgradedWithParam.AddParameter("city", EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.String, isNullable: false)); model.AddElement(isCustomerUpgradedWithParam); EdmFunction isCustomerLocal = new EdmFunction( "NS", "IsLocal", returnType, isBound: true, entitySetPathExpression: null, isComposable: false); isCustomerLocal.AddParameter("entity", new EdmEntityTypeReference(customer, false)); model.AddElement(isCustomerLocal); EdmFunction entityFunction = new EdmFunction( "NS", "GetCustomer", returnType, isBound: true, entitySetPathExpression: null, isComposable: false); entityFunction.AddParameter("entity", new EdmEntityTypeReference(customer, false)); entityFunction.AddParameter("customer", new EdmEntityTypeReference(customer, false)); model.AddElement(entityFunction); EdmFunction getOrder = new EdmFunction( "NS", "GetOrder", order.ToEdmTypeReference(false), isBound: true, entitySetPathExpression: null, isComposable: true); // Composable getOrder.AddParameter("entity", new EdmEntityTypeReference(customer, false)); getOrder.AddParameter("orderId", intType); model.AddElement(getOrder); // functions bound to collection EdmFunction isAllUpgraded = new EdmFunction("NS", "IsAllUpgraded", returnType, isBound: true, entitySetPathExpression: null, isComposable: false); isAllUpgraded.AddParameter("entityset", new EdmCollectionTypeReference(new EdmCollectionType(new EdmEntityTypeReference(customer, false)))); isAllUpgraded.AddParameter("param", intType); model.AddElement(isAllUpgraded); EdmFunction isSpecialAllUpgraded = new EdmFunction("NS", "IsSpecialAllUpgraded", returnType, isBound: true, entitySetPathExpression: null, isComposable: false); isSpecialAllUpgraded.AddParameter("entityset", new EdmCollectionTypeReference(new EdmCollectionType(new EdmEntityTypeReference(specialCustomer, false)))); isSpecialAllUpgraded.AddParameter("param", intType); model.AddElement(isSpecialAllUpgraded); // navigation properties EdmNavigationProperty ordersNavProp = customer.AddUnidirectionalNavigation( new EdmNavigationPropertyInfo { Name = "Orders", TargetMultiplicity = EdmMultiplicity.Many, Target = order }); mary.AddNavigationTarget(ordersNavProp, orders); vipCustomer.AddNavigationTarget(ordersNavProp, orders); customers.AddNavigationTarget(ordersNavProp, orders); orders.AddNavigationTarget( order.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo { Name = "Customer", TargetMultiplicity = EdmMultiplicity.ZeroOrOne, Target = customer }), customers); // navigation properties on derived types. EdmNavigationProperty specialOrdersNavProp = specialCustomer.AddUnidirectionalNavigation( new EdmNavigationPropertyInfo { Name = "SpecialOrders", TargetMultiplicity = EdmMultiplicity.Many, Target = order }); vipCustomer.AddNavigationTarget(specialOrdersNavProp, orders); customers.AddNavigationTarget(specialOrdersNavProp, orders); orders.AddNavigationTarget( specialOrder.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo { Name = "SpecialCustomer", TargetMultiplicity = EdmMultiplicity.ZeroOrOne, Target = customer }), customers); model.SetAnnotationValue <BindableOperationFinder>(model, new BindableOperationFinder(model)); // set properties Model = model; Container = container; Customer = customer; Order = order; Address = address; Account = account; SpecialCustomer = specialCustomer; SpecialOrder = specialOrder; Orders = orders; Customers = customers; VipCustomer = vipCustomer; Mary = mary; RootOrder = rootOrder; OrderLine = orderLine; OrderLines = orderLines; NonContainedOrderLines = nonContainedOrderLines; UpgradeCustomer = upgrade; UpgradeSpecialCustomer = specialUpgrade; CustomerName = customerName; IsCustomerUpgraded = isCustomerUpgradedWithParam; IsSpecialCustomerUpgraded = IsSpecialUpgraded; Tag = tag; }
private IEdmModel GetEdmModelWithOperations(out IEdmEntityType customerType, out IEdmEntitySet customers) { EdmModel model = new EdmModel(); EdmEntityType customer = new EdmEntityType("NS", "Customer"); customerType = customer; customer.AddKeys(customer.AddStructuralProperty("ID", EdmPrimitiveTypeKind.Int32)); model.AddElement(customer); EdmAction upgradeAll = new EdmAction("NS", "UpgradeAll", returnType: null, isBound: true, entitySetPathExpression: null); upgradeAll.AddParameter("entityset", new EdmCollectionTypeReference(new EdmCollectionType(new EdmEntityTypeReference(customer, false)))); model.AddElement(upgradeAll); IEdmTypeReference returnType = EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.Boolean, isNullable: false); IEdmTypeReference stringType = EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.String, isNullable: false); IEdmTypeReference intType = EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.Int32, isNullable: false); EdmFunction IsAnyUpgraded = new EdmFunction( "NS", "IsAnyUpgraded", returnType, isBound: true, entitySetPathExpression: null, isComposable: false); EdmCollectionType edmCollectionType = new EdmCollectionType(new EdmEntityTypeReference(customer, false)); IsAnyUpgraded.AddParameter("entityset", new EdmCollectionTypeReference(edmCollectionType)); model.AddElement(IsAnyUpgraded); EdmFunction isCustomerUpgradedWithParam = new EdmFunction( "NS", "IsUpgradedWithParam", returnType, isBound: true, entitySetPathExpression: null, isComposable: false); isCustomerUpgradedWithParam.AddParameter("entity", new EdmEntityTypeReference(customer, false)); isCustomerUpgradedWithParam.AddParameter("city", EdmCoreModel.Instance.GetPrimitive(EdmPrimitiveTypeKind.String, isNullable: false)); model.AddElement(isCustomerUpgradedWithParam); EdmFunction isAllUpgraded = new EdmFunction("NS", "IsAllUpgraded", returnType, isBound: true, entitySetPathExpression: null, isComposable: false); isAllUpgraded.AddParameter("entityset", new EdmCollectionTypeReference(new EdmCollectionType(new EdmEntityTypeReference(customer, false)))); isAllUpgraded.AddParameter("param", intType); model.AddElement(isAllUpgraded); EdmFunction getSalaray = new EdmFunction("NS", "GetWholeSalary", intType, isBound: true, entitySetPathExpression: null, isComposable: false); getSalaray.AddParameter("entityset", new EdmCollectionTypeReference(new EdmCollectionType(new EdmEntityTypeReference(customer, false)))); getSalaray.AddParameter("minSalary", intType); getSalaray.AddOptionalParameter("maxSalary", intType); getSalaray.AddOptionalParameter("aveSalary", intType, "129"); model.AddElement(getSalaray); EdmEntityContainer container = new EdmEntityContainer("NS", "ModelWithInheritance"); model.AddElement(container); customers = container.AddEntitySet("Customers", customer); return(model); }
private static IEdmTypeReference GetEdmTypeReference(Dictionary <Type, IEdmType> availableTypes, IEdmTypeConfiguration configuration, bool nullable) { Contract.Assert(availableTypes != null); if (configuration == null) { return(null); } EdmTypeKind kind = configuration.Kind; if (kind == EdmTypeKind.Collection) { CollectionTypeConfiguration collectionType = (CollectionTypeConfiguration)configuration; EdmCollectionType edmCollectionType = new EdmCollectionType(GetEdmTypeReference(availableTypes, collectionType.ElementType, nullable)); return(new EdmCollectionTypeReference(edmCollectionType)); } else { Type configurationClrType = TypeHelper.GetUnderlyingTypeOrSelf(configuration.ClrType); if (!TypeHelper.IsEnum(configurationClrType)) { configurationClrType = configuration.ClrType; } IEdmType type; if (availableTypes.TryGetValue(configurationClrType, out type)) { if (kind == EdmTypeKind.Complex) { return(new EdmComplexTypeReference((IEdmComplexType)type, nullable)); } else if (kind == EdmTypeKind.Entity) { return(new EdmEntityTypeReference((IEdmEntityType)type, nullable)); } else if (kind == EdmTypeKind.Enum) { return(new EdmEnumTypeReference((IEdmEnumType)type, nullable)); } else { throw Error.InvalidOperation(SRResources.UnsupportedEdmTypeKind, kind.ToString()); } } else if (configuration.Kind == EdmTypeKind.Primitive) { PrimitiveTypeConfiguration primitiveTypeConfiguration = (PrimitiveTypeConfiguration)configuration; EdmPrimitiveTypeKind typeKind = EdmTypeBuilder.GetTypeKind(primitiveTypeConfiguration.ClrType); return(EdmCoreModel.Instance.GetPrimitive(typeKind, nullable)); } else if (configuration.Kind == EdmTypeKind.Untyped) { return(EdmCoreModel.Instance.GetUntyped()); } else { throw Error.InvalidOperation(SRResources.NoMatchingIEdmTypeFound, configuration.FullName); } } }
/// <summary> /// This method is called by method call like Where/OfType/SelectMany and so on /// to create a model reference for whole function call. /// </summary> /// <param name="methodCall"> /// An method call expression node. /// </param> /// <param name="source"> /// The parameter model reference. /// </param> /// <param name="model"> /// The edm model. /// </param> /// <returns> /// A reference to the model element /// that represents the expression node. /// </returns> private static QueryModelReference ComputeQueryModelReference( MethodCallExpression methodCall, QueryModelReference source, IEdmModel model) { var method = methodCall.Method; // source is a sequence of T and output is also a sequence of T var sourceType = method.GetParameters()[0].ParameterType.FindGenericType(typeof(IEnumerable <>)); var resultType = method.ReturnType.FindGenericType(typeof(IEnumerable <>)); if (sourceType == resultType) { return(new QueryModelReference(source.EntitySet, source.Type)); } Type resultElementType = null; if (resultType != null) { resultElementType = resultType.GenericTypeArguments[0]; } // In case sourceType IEnumerable<Person> and resultType is // IEnumerable <SelectExpandBinder.SelectAllAndExpand<Person>> // or IEnumerable<SelectExpandBinder.SelectAll<Person>> // or IEnumerable<SelectExpandBinder.SelectSome<Person>> // or IEnumerable<SelectExpandBinder.SelectSomeAndInheritance<Person>> if (sourceType != null && resultType != null) { var resultGenericType = resultElementType; if (resultGenericType.IsGenericType) { var resultFinalElementType = resultGenericType.GenericTypeArguments[0]; var sourceElementType = sourceType.GenericTypeArguments[0]; // Handle source is type of sub class and result is a base class if (resultFinalElementType.IsAssignableFrom(sourceElementType)) { return(new QueryModelReference(source.EntitySet, source.Type)); } } } // In this case, the sourceType is null if (method.Name.Equals(MethodNameOfType)) { // Did not consider multiple namespaces have same entity type case or customized namespace var edmEntityType = model.FindDeclaredType(resultElementType.FullName); var collectionType = new EdmCollectionType( new EdmEntityTypeReference((IEdmEntityType)edmEntityType, false)); return(new QueryModelReference(source.EntitySet, collectionType)); } // Till here, it means the result is not part of previous result and entity set will be null // This mean result is a collection as resultType is IEnumerable<> if (resultType != null) { // Did not consider multiple namespaces have same entity type case or customized namespace var edmElementType = model.FindDeclaredType(resultElementType.FullName); // This means result is collection of Entity/Complex/Enum IEdmTypeReference edmTypeReference = null; if (edmElementType != null) { var edmType = edmElementType as IEdmType; edmTypeReference = edmType.GetTypeReference(); if (edmTypeReference != null) { var collectionType = new EdmCollectionType(edmTypeReference); return(new QueryModelReference(null, collectionType)); } } // TODO Here means a collection of primitive type } // TODO Need to handle single result case // TODO GitHubIssue#29 : Handle projection operators in query expression return(null); }
/// <summary> /// Try to bind namespace-qualified type cast segment. /// </summary> internal static bool TryBindTypeCastSegment(string identifier, string parenthesisExpressions, IEdmModel model, IList <PathSegment> path, PathParserSettings settings) { if (identifier == null || identifier.IndexOf('.') < 0) { // type cast should be namespace-qualified name return(false); } PathSegment preSegment = path.LastOrDefault(); if (preSegment == null) { // type cast should not be the first segment. return(false); } IEdmSchemaType schemaType = model.ResolveType(identifier, settings.EnableCaseInsensitive); if (schemaType == null) { return(false); } IEdmType targetEdmType = schemaType as IEdmType; if (targetEdmType == null) { return(false); } IEdmType previousEdmType = preSegment.EdmType; bool isNullable = false; if (previousEdmType.TypeKind == EdmTypeKind.Collection) { previousEdmType = ((IEdmCollectionType)previousEdmType).ElementType.Definition; isNullable = ((IEdmCollectionType)previousEdmType).ElementType.IsNullable; } if (!targetEdmType.IsOrInheritsFrom(previousEdmType) && !previousEdmType.IsOrInheritsFrom(targetEdmType)) { throw new Exception($"Type cast {targetEdmType.FullTypeName()} has no relationship with previous {previousEdmType.FullTypeName()}."); } // We want the type of the type segment to be a collection if the previous segment was a collection IEdmType actualTypeOfTheTypeSegment = targetEdmType; if (preSegment.EdmType.TypeKind == EdmTypeKind.Collection) { var actualEntityTypeOfTheTypeSegment = targetEdmType as IEdmEntityType; if (actualEntityTypeOfTheTypeSegment != null) { actualTypeOfTheTypeSegment = new EdmCollectionType(new EdmEntityTypeReference(actualEntityTypeOfTheTypeSegment, isNullable)); } else { // Complex collection supports type cast too. var actualComplexTypeOfTheTypeSegment = actualTypeOfTheTypeSegment as IEdmComplexType; if (actualComplexTypeOfTheTypeSegment != null) { actualTypeOfTheTypeSegment = new EdmCollectionType(new EdmComplexTypeReference(actualComplexTypeOfTheTypeSegment, isNullable)); } else { throw new Exception($"Invalid type cast of {identifier}, it should be entity or complex."); } } } TypeSegment typeCast = new TypeSegment(actualTypeOfTheTypeSegment, preSegment.EdmType, preSegment.NavigationSource, identifier); path.Add(typeCast); TryBindKeySegment(parenthesisExpressions, path); return(true); }
private static EdmCollectionTypeReference CreateCultureValuesCollectionTypeReference(IEdmComplexTypeReference cultureValueTypeReference) { var collectionType = new EdmCollectionType(cultureValueTypeReference); return(new EdmCollectionTypeReference(collectionType)); }
public void WriteUntypedValueTest() { EdmModel edmModel = new EdmModel(); var jsonType = new EdmComplexType("TestModel", "JsonType"); var jsonTypeRef = new EdmComplexTypeReference(jsonType, isNullable: true); edmModel.AddElement(jsonType); var collectionType = new EdmCollectionType(jsonTypeRef); var collectionTypeRef = new EdmCollectionTypeReference(collectionType); var entityType = new EdmEntityType("TestModel", "EntityType"); entityType.AddStructuralProperty("Value", jsonTypeRef); entityType.AddStructuralProperty("CollectionValue", collectionTypeRef); edmModel.AddElement(entityType); var container = new EdmEntityContainer("TestModel", "DefaultContainer"); container.AddEntitySet("EntitySet", entityType); edmModel.AddElement(container); const string JsonFormat = "$(NL){{{0},\"Value\":{1}}}"; IEnumerable <PropertyPayloadTestCase> testCases = new[] { new PropertyPayloadTestCase { DebugDescription = "Null.", Property = new ODataProperty { Name = "Value", Value = new ODataUntypedValue() { RawValue = "null" } }, }, new PropertyPayloadTestCase { DebugDescription = "Integer.", Property = new ODataProperty { Name = "Value", Value = new ODataUntypedValue() { RawValue = "42" } }, }, new PropertyPayloadTestCase { DebugDescription = "Float.", Property = new ODataProperty { Name = "Value", Value = new ODataUntypedValue() { RawValue = "3.1415" } }, }, new PropertyPayloadTestCase { DebugDescription = "String.", Property = new ODataProperty { Name = "Value", Value = new ODataUntypedValue() { RawValue = "\"string\"" } }, }, new PropertyPayloadTestCase { DebugDescription = "Array of elements of mixed types.", Property = new ODataProperty { Name = "Value", Value = new ODataUntypedValue() { RawValue = "[1, 2, \"abc\"]" } }, }, new PropertyPayloadTestCase { DebugDescription = "Array of arrays.", Property = new ODataProperty { Name = "Value", Value = new ODataUntypedValue() { RawValue = "[ [1, \"abc\"], [2, \"def\"], [[3],[4, 5]] ]" } }, }, new PropertyPayloadTestCase { DebugDescription = "Negative - empty RawValue", Property = new ODataProperty { Name = "Value", Value = new ODataUntypedValue() { RawValue = string.Empty }, }, ExpectedException = ODataExpectedExceptions.ODataException( TextRes.ODataJsonLightValueSerializer_MissingRawValueOnUntyped), }, new PropertyPayloadTestCase { DebugDescription = "Collection of Edm.Untyped elements.", Property = new ODataProperty { Name = "CollectionValue", Value = new ODataCollectionValue() { TypeName = "Collection(TestModel.JsonType)", Items = new object[] { new ODataUntypedValue() { RawValue = "\"string\"" }, new ODataUntypedValue() { RawValue = "[1, 2, \"abc\"]" }, new ODataUntypedValue() { RawValue = "3.1415" } } } }, }, new PropertyPayloadTestCase { DebugDescription = "Integer.", Property = new ODataProperty { Name = "Value", Value = new ODataPrimitiveValue(42) }, }, new PropertyPayloadTestCase { DebugDescription = "Float.", Property = new ODataProperty { Name = "Value", Value = new ODataPrimitiveValue(3.1415) }, }, new PropertyPayloadTestCase { DebugDescription = "String.", Property = new ODataProperty { Name = "Value", Value = new ODataPrimitiveValue("string") }, }, }; IEnumerable <PayloadWriterTestDescriptor <ODataProperty> > testDescriptors = testCases.Select(testCase => new PayloadWriterTestDescriptor <ODataProperty>( this.Settings, testCase.Property, tc => new JsonWriterTestExpectedResults(this.Settings.ExpectedResultSettings) { Json = string.Format( CultureInfo.InvariantCulture, JsonFormat, JsonLightWriterUtils.GetMetadataUrlPropertyForEntry("EntitySet"), GetExpectedJson(testCase.Property.Value)), FragmentExtractor = (result) => result.RemoveAllAnnotations(false), ExpectedException2 = testCase.ExpectedException, }) { DebugDescription = testCase.DebugDescription, Model = edmModel, }); this.CombinatorialEngineProvider.RunCombinations( testDescriptors, this.WriterTestConfigurationProvider.JsonLightFormatConfigurationsWithIndent, (testDescriptor, testConfiguration) => { TestWriterUtils.WriteAndVerifyTopLevelContent( testDescriptor, testConfiguration, (messageWriter) => { messageWriter.PrivateSettings.Validations = ~ValidationKinds.ThrowOnUndeclaredPropertyForNonOpenType; messageWriter.WriteProperty(testDescriptor.PayloadItems.Single()); }, this.Assert, baselineLogger: this.Logger); }); }
private void WriteTopLevelComplexCollectionProperty(bool inherit) { EdmModel model = new EdmModel(); EdmComplexType complexType = AddAndGetComplexType(model); if (inherit) { EdmComplexType derivedComplexType = new EdmComplexType("Fake", "DerivedComplexType", complexType); derivedComplexType.AddStructuralProperty("D1", EdmPrimitiveTypeKind.String); model.AddElement(derivedComplexType); } EdmEntityType entityType = AddAndGetEntityType(model); var collectionOfComplexType = new EdmCollectionType(new EdmComplexTypeReference(complexType, true)); entityType.AddStructuralProperty("CollectionOfComplexP", new EdmCollectionTypeReference(collectionOfComplexType)); var entitySet = GetEntitySet(model, entityType); var requestUri = new Uri("http://temp.org/FakeSet('parent')/CollectionOfComplexP"); var odataUri = new ODataUri { RequestUri = requestUri }; odataUri.Path = new ODataUriParser(model, new Uri("http://temp.org/"), requestUri).ParsePath(); ODataResourceSet collectionP = new ODataResourceSet(); ODataResource complexP = new ODataResource() { Properties = new[] { new ODataProperty { Name = "P1", Value = "complexValue" }, } }; Action <ODataWriter> write = (writer) => { writer.WriteStart(collectionP); writer.WriteStart(complexP); writer.WriteEnd(); writer.WriteEnd(); }; var expected = "{" + "\"@odata.context\":\"http://temp.org/$metadata#FakeSet('parent')/CollectionOfComplexP\"," + "\"value\":" + "[" + "{" + "\"P1\":\"complexValue\"" + "}" + "]" + "}"; if (inherit) { ODataResource dComplexP = new ODataResource() { TypeName = "Fake.DerivedComplexType", Properties = new[] { new ODataProperty { Name = "P1", Value = "complexValue" }, new ODataProperty { Name = "D1", Value = "derivedComplexValue" } } }; write = (writer) => { writer.WriteStart(collectionP); writer.WriteStart(complexP); writer.WriteEnd(); writer.WriteStart(dComplexP); writer.WriteEnd(); writer.WriteEnd(); }; expected = "{" + "\"@odata.context\":\"http://temp.org/$metadata#FakeSet('parent')/CollectionOfComplexP\"," + "\"value\":" + "[" + "{" + "\"P1\":\"complexValue\"" + "}," + "{" + "\"@odata.type\":\"#Fake.DerivedComplexType\"," + "\"P1\":\"complexValue\"," + "\"D1\":\"derivedComplexValue\"" + "}" + "]" + "}"; } var actual = WriteJsonLightEntry( isRequest: false, serviceDocumentUri: new Uri("http://temp.org/"), specifySet: false, odataEntry: null, entitySet: null, resourceType: complexType, odataUri: odataUri, writeAction: write, isResourceSet: true, model: model); actual.Should().Be(expected); }
/// <summary> /// /// </summary> /// <param name="context"></param> public virtual bool AppliesToAction(ODataControllerActionContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } ActionModel action = context.Action; if (context.EntitySet == null && context.Singleton == null) { return(false); } IEdmNavigationSource navigationSource = context.EntitySet == null ? (IEdmNavigationSource)context.Singleton : (IEdmNavigationSource)context.EntitySet; IEdmModel model = context.Model; string prefix = context.Prefix; IEdmEntityType entityType = navigationSource.EntityType(); bool hasKeyParameter = HasKeyParameter(entityType, action); // found int keyNumber = entityType.Key().Count(); IEdmType bindType = entityType; if (!hasKeyParameter) { // bond to collection bindType = new EdmCollectionType(new EdmEntityTypeReference(entityType, true)); keyNumber = 0; } string actionName = action.ActionMethod.Name; var operations = model.FindBoundOperations(bindType).Where(p => p.Name == actionName); var actions = operations.OfType <IEdmAction>().ToList(); if (actions.Count == 1) // action overload on binding type, only one action overload on the same binding type { if (action.Parameters.Any(p => p.ParameterType == typeof(ODataActionParameters))) { // we find a action route IList <ODataSegmentTemplate> segments = new List <ODataSegmentTemplate>(); if (context.EntitySet != null) { segments.Add(new EntitySetSegmentTemplate(context.EntitySet)); } else { segments.Add(new SingletonSegmentTemplate(context.Singleton)); } if (hasKeyParameter) { segments.Add(new KeySegmentTemplate(entityType)); } segments.Add(new ActionSegmentTemplate(actions[0], false)); ODataPathTemplate template = new ODataPathTemplate(segments); action.AddSelector(prefix, model, template); return(true); } } var functions = operations.OfType <IEdmFunction>().ToList(); IEdmFunction function = FindMatchFunction(keyNumber, functions, action); if (function != null) { IList <ODataSegmentTemplate> segments = new List <ODataSegmentTemplate>(); if (context.EntitySet != null) { segments.Add(new EntitySetSegmentTemplate(context.EntitySet)); } else { segments.Add(new SingletonSegmentTemplate(context.Singleton)); } if (hasKeyParameter) { segments.Add(new KeySegmentTemplate(entityType)); } segments.Add(new FunctionSegmentTemplate(function, false)); ODataPathTemplate template = new ODataPathTemplate(segments); action.AddSelector(prefix, model, template); return(true); } // in OData operationImport routing convention, all action are processed by default // even it's not a really edm operation import call. return(false); }
public ODataJsonLightReaderEnumIntegrationTests() { EdmModel tmpModel = new EdmModel(); // enum without flags var enumType = new EdmEnumType("NS", "Color"); var red = new EdmEnumMember(enumType, "Red", new EdmIntegerConstant(1)); enumType.AddMember(red); enumType.AddMember("Green", new EdmIntegerConstant(2)); enumType.AddMember("Blue", new EdmIntegerConstant(3)); tmpModel.AddElement(enumType); // enum with flags var enumFlagsType = new EdmEnumType("NS", "ColorFlags", isFlags: true); enumFlagsType.AddMember("Red", new EdmIntegerConstant(1)); enumFlagsType.AddMember("Green", new EdmIntegerConstant(2)); enumFlagsType.AddMember("Blue", new EdmIntegerConstant(4)); tmpModel.AddElement(enumFlagsType); this.entityType = new EdmEntityType("NS", "MyEntityType", isAbstract: false, isOpen: true, baseType: null); EdmStructuralProperty floatId = new EdmStructuralProperty(this.entityType, "FloatId", EdmCoreModel.Instance.GetSingle(false)); this.entityType.AddKeys(floatId); this.entityType.AddProperty(floatId); var enumTypeReference = new EdmEnumTypeReference(enumType, true); this.entityType.AddProperty(new EdmStructuralProperty(this.entityType, "Color", enumTypeReference)); var enumFlagsTypeReference = new EdmEnumTypeReference(enumFlagsType, false); this.entityType.AddProperty(new EdmStructuralProperty(this.entityType, "ColorFlags", enumFlagsTypeReference)); // enum in complex type EdmComplexType myComplexType = new EdmComplexType("NS", "MyComplexType"); myComplexType.AddProperty(new EdmStructuralProperty(myComplexType, "MyColorFlags", enumFlagsTypeReference)); myComplexType.AddProperty(new EdmStructuralProperty(myComplexType, "Height", EdmCoreModel.Instance.GetDouble(false))); tmpModel.AddElement(myComplexType); this.entityType.AddProperty(new EdmStructuralProperty(this.entityType, "MyComplexType", new EdmComplexTypeReference(myComplexType, true))); // enum in derived complex type EdmComplexType myDerivedComplexType = new EdmComplexType("NS", "MyDerivedComplexType", myComplexType, false); myDerivedComplexType.AddProperty(new EdmStructuralProperty(myDerivedComplexType, "MyDerivedColorFlags", new EdmEnumTypeReference(enumFlagsType, false))); tmpModel.AddElement(myDerivedComplexType); // enum in collection type EdmCollectionType myCollectionType = new EdmCollectionType(enumFlagsTypeReference); this.entityType.AddProperty(new EdmStructuralProperty(this.entityType, "MyCollectionType", new EdmCollectionTypeReference(myCollectionType))); tmpModel.AddElement(this.entityType); var defaultContainer = new EdmEntityContainer("NS", "DefaultContainer_sub"); this.entitySet = new EdmEntitySet(defaultContainer, "MySet", this.entityType); defaultContainer.AddEntitySet(this.entitySet.Name, this.entityType); tmpModel.AddElement(defaultContainer); this.userModel = TestUtils.WrapReferencedModelsToMainModel("NS", "DefaultContainer", tmpModel); }
/// <summary> /// Convert to collection type reference from element type reference /// </summary> /// <param name="elementTypeReference">The element type reference</param> /// <returns>The colleciton type reference</returns> public static IEdmCollectionTypeReference ToCollectionTypeReference(this IEdmTypeReference elementTypeReference) { var collectionDefinition = new EdmCollectionType(elementTypeReference); return(collectionDefinition.ToTypeReference()); }
/// <summary> /// This method is called by method call like Where/OfType/SelectMany and so on /// to create a model reference for whole function call. /// </summary> /// <param name="methodCall"> /// An method call expression node. /// </param> /// <param name="source"> /// The parameter model reference. /// </param> /// <param name="model"> /// The edm model. /// </param> /// <returns> /// A reference to the model element /// that represents the expression node. /// </returns> private static QueryModelReference ComputeQueryModelReference( MethodCallExpression methodCall, QueryModelReference source, IEdmModel model) { var method = methodCall.Method; // source is a sequence of T and output is also a sequence of T var sourceType = method.GetParameters()[0].ParameterType.FindGenericType(typeof(IEnumerable<>)); var resultType = method.ReturnType.FindGenericType(typeof(IEnumerable<>)); if (sourceType == resultType) { return new QueryModelReference(source.EntitySet, source.Type); } Type resultElementType = null; if (resultType != null) { resultElementType = resultType.GenericTypeArguments[0]; } // In case sourceType IEnumerable<Person> and resultType is // IEnumerable <SelectExpandBinder.SelectAllAndExpand<Person>> // or IEnumerable<SelectExpandBinder.SelectAll<Person>> // or IEnumerable<SelectExpandBinder.SelectSome<Person>> // or IEnumerable<SelectExpandBinder.SelectSomeAndInheritance<Person>> if (sourceType != null && resultType != null) { var resultGenericType = resultElementType; if (resultGenericType.IsGenericType) { var resultFinalElementType = resultGenericType.GenericTypeArguments[0]; var sourceElementType = sourceType.GenericTypeArguments[0]; // Handle source is type of sub class and result is a base class if (resultFinalElementType.IsAssignableFrom(sourceElementType)) { return new QueryModelReference(source.EntitySet, source.Type); } } } // In this case, the sourceType is null if (method.Name.Equals(MethodNameOfType)) { // Did not consider multiple namespaces have same entity type case or customized namespace var edmEntityType = model.FindDeclaredType(resultElementType.FullName); var collectionType = new EdmCollectionType( new EdmEntityTypeReference((IEdmEntityType)edmEntityType, false)); return new QueryModelReference(source.EntitySet, collectionType); } // Till here, it means the result is not part of previous result and entity set will be null // This mean result is a collection as resultType is IEnumerable<> if (resultType != null) { // Did not consider multiple namespaces have same entity type case or customized namespace var edmElementType = model.FindDeclaredType(resultElementType.FullName); // This means result is collection of Entity/Complex/Enum IEdmTypeReference edmTypeReference = null; if (edmElementType != null) { var edmType = edmElementType as IEdmType; edmTypeReference = edmType.GetTypeReference(); if (edmTypeReference != null) { var collectionType = new EdmCollectionType(edmTypeReference); return new QueryModelReference(null, collectionType); } } // TODO Here means a collection of primitive type } // TODO Need to handle single result case // TODO GitHubIssue#29 : Handle projection operators in query expression return null; }
public void CollectionValueTest() { EdmModel edmModel = new EdmModel(); EdmComplexType edmComplexTypeMyComplexType = edmModel.ComplexType("MyComplexType", ModelNamespace); edmComplexTypeMyComplexType.Property("P1", EdmPrimitiveTypeKind.Int32, false).Property("P2", EdmPrimitiveTypeKind.String, true); edmModel.Fixup(); var edmCollectionTypeOfIntegerType = new EdmCollectionType(EdmCoreModel.Instance.GetInt32(false)); var edmCollectionTypeOfMyComplexType = new EdmCollectionType(new EdmComplexTypeReference(edmComplexTypeMyComplexType, true)); // Create payloads of the collection properties IEnumerable <PayloadReaderTestDescriptor> testDescriptors = new[] { // Empty element collection new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.PrimitiveMultiValue(EntityModelUtils.GetCollectionTypeName("Edm.Int32")) .XmlValueRepresentation(new XNode[0]) .WithTypeAnnotation(edmCollectionTypeOfIntegerType), PayloadEdmModel = edmModel, }, // Collections containing collections are not supported new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.PrimitiveMultiValue() .XmlValueRepresentation("<m:element />", EntityModelUtils.GetCollectionTypeName(EntityModelUtils.GetCollectionTypeName("Edm.String")), null) .WithTypeAnnotation(edmCollectionTypeOfIntegerType), PayloadEdmModel = edmModel, ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_NestedCollectionsAreNotSupported"), }, }; var primitivePayloadsWithPadding = new CollectionPaddingPayloadTextCase <PrimitiveMultiValue>[] { new CollectionPaddingPayloadTextCase <PrimitiveMultiValue> { XmlValue = "{0}", PayloadElement = PayloadBuilder.PrimitiveMultiValue(EntityModelUtils.GetCollectionTypeName("Edm.Int32")) .WithTypeAnnotation(edmCollectionTypeOfIntegerType) }, new CollectionPaddingPayloadTextCase <PrimitiveMultiValue> { XmlValue = "{0}<m:element>42</m:element>", PayloadElement = PayloadBuilder.PrimitiveMultiValue(EntityModelUtils.GetCollectionTypeName("Edm.Int32")) .Item(42) .WithTypeAnnotation(edmCollectionTypeOfIntegerType) }, new CollectionPaddingPayloadTextCase <PrimitiveMultiValue> { XmlValue = "<m:element>42</m:element>{0}", PayloadElement = PayloadBuilder.PrimitiveMultiValue(EntityModelUtils.GetCollectionTypeName("Edm.Int32")) .Item(42) .WithTypeAnnotation(edmCollectionTypeOfIntegerType) }, }; var complexPayloadsWithPadding = new CollectionPaddingPayloadTextCase <ComplexMultiValue>[] { new CollectionPaddingPayloadTextCase <ComplexMultiValue> { XmlValue = "<m:element><d:P1>42</d:P1></m:element>{0}<m:element><d:P2>test</d:P2></m:element>", PayloadElement = PayloadBuilder.ComplexMultiValue(EntityModelUtils.GetCollectionTypeName("TestModel.MyComplexType")) .Item(PayloadBuilder.ComplexValue("TestModel.MyComplexType").PrimitiveProperty("P1", 42).AddAnnotation(new SerializationTypeNameTestAnnotation() { TypeName = null })) .Item(PayloadBuilder.ComplexValue("TestModel.MyComplexType").PrimitiveProperty("P2", "test").AddAnnotation(new SerializationTypeNameTestAnnotation() { TypeName = null })) .WithTypeAnnotation(edmCollectionTypeOfMyComplexType) }, }; var xmlPadding = new CollectionXmlPadding[] { // Nothing new CollectionXmlPadding { Padding = string.Empty, }, // Whitespace only new CollectionXmlPadding { Padding = " \r\n\t", }, // Insignificant nodes new CollectionXmlPadding { Padding = "<!--s--> <?value?>", }, // Element in no namespace new CollectionXmlPadding { Padding = "<foo xmlns=''/>", }, // Element in custom namespace new CollectionXmlPadding { Padding = "<c:foo xmlns:c='uri' attr='1'><c:child/>text</c:foo>", }, // Element in metadata namespace (should be ignored as well) new CollectionXmlPadding { Padding = "<m:properties/>", }, // Element in atom namespace (should also be ignored) new CollectionXmlPadding { Padding = "<entry/>", }, // Significant nodes - will be ignored new CollectionXmlPadding { Padding = "some text <![CDATA[cdata]]>", }, // Element in the d namespace should fail new CollectionXmlPadding { Padding = "<d:foo/>", ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomPropertyAndValueDeserializer_InvalidCollectionElement", "foo", "http://docs.oasis-open.org/odata/ns/metadata"), }, // Element in the d namespace should fail (wrong name) new CollectionXmlPadding { Padding = "<d:Element/>", ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomPropertyAndValueDeserializer_InvalidCollectionElement", "Element", "http://docs.oasis-open.org/odata/ns/metadata"), }, }; testDescriptors = testDescriptors.Concat(this.CreatePayloadWithPaddingTestDescriptor( primitivePayloadsWithPadding, xmlPadding, edmModel)); testDescriptors = testDescriptors.Concat(this.CreatePayloadWithPaddingTestDescriptor( complexPayloadsWithPadding, xmlPadding, edmModel)); testDescriptors = testDescriptors.Select(td => td.InProperty()); this.CombinatorialEngineProvider.RunCombinations( testDescriptors, this.ReaderTestConfigurationProvider.AtomFormatConfigurations, (testDescriptor, testConfiguration) => { testDescriptor.RunTest(testConfiguration); }); }
/// <summary> /// Creates a collection value type for the specified <paramref name="itemTypeReference"/>. /// </summary> /// <param name="itemTypeReference">The <see cref="IEdmPrimitiveTypeReference"/> for the item type.</param> /// <returns>The created <see cref="IEdmCollectionTypeReference"/>.</returns> public static IEdmCollectionTypeReference ToCollectionTypeReference(this IEdmPrimitiveTypeReference itemTypeReference) { IEdmCollectionType collectionType = new EdmCollectionType(itemTypeReference); return((IEdmCollectionTypeReference)ToTypeReference(collectionType)); }
public void CollectionWithHeterogenousItemsTest() { EdmModel edmModel = new EdmModel(); EdmComplexType edmComplexTypeMyComplexType = edmModel.ComplexType("MyComplexType", ModelNamespace); edmComplexTypeMyComplexType.Property("P1", EdmPrimitiveTypeKind.Int32, false).Property("P2", EdmPrimitiveTypeKind.String, true); edmModel.Fixup(); var edmCollectionTypeOfIntegerType = new EdmCollectionType(EdmCoreModel.Instance.GetInt32(false)); var edmCollectionTypeOfStringType = new EdmCollectionType(EdmCoreModel.Instance.GetString(true)); IEnumerable <PayloadReaderTestDescriptor> testDescriptors = new[] { // Primitive collection with complex item new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.PrimitiveMultiValue(EntityModelUtils.GetCollectionTypeName("Edm.String")) .XmlValueRepresentation("<m:element><d:P1>0</d:P1><d:P2>Foo</d:P2></m:element>", EntityModelUtils.GetCollectionTypeName("Edm.String"), null) .WithTypeAnnotation(edmCollectionTypeOfStringType), PayloadEdmModel = edmModel, ExpectedException = ODataExpectedExceptions.ODataException("XmlReaderExtension_InvalidNodeInStringValue", "Element"), }, new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.PrimitiveMultiValue(EntityModelUtils.GetCollectionTypeName("Edm.Int32")) .XmlValueRepresentation("<m:element>0</m:element><m:element><d:P1>0</d:P1><d:P2>Foo</d:P2></m:element>", EntityModelUtils.GetCollectionTypeName("Edm.Int32"), null) .WithTypeAnnotation(edmCollectionTypeOfIntegerType), PayloadEdmModel = edmModel, ExpectedException = ODataExpectedExceptions.ODataException("XmlReaderExtension_InvalidNodeInStringValue", "Element"), }, // Complex collection with primitive item // Note - the text nodes (of the primitive items) are ignored in complex values - leaving empty complex values new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.ComplexMultiValue(EntityModelUtils.GetCollectionTypeName("TestModel.MyComplexType")) .Item(PayloadBuilder.ComplexValue("TestModel.MyComplexType").PrimitiveProperty("P1", 987).AddAnnotation(new SerializationTypeNameTestAnnotation() { TypeName = null })) .Item(PayloadBuilder.ComplexValue("TestModel.MyComplexType").PrimitiveProperty("P1", 123).AddAnnotation(new SerializationTypeNameTestAnnotation() { TypeName = null })) .XmlValueRepresentation("<m:element>Foo<d:P1>987</d:P1></m:element><m:element><d:P1>123</d:P1>Bar</m:element>", EntityModelUtils.GetCollectionTypeName("TestModel.MyComplexType"), null), PayloadEdmModel = edmModel, }, // Primitive collection containing a primitive and a nested collection new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.PrimitiveMultiValue(EntityModelUtils.GetCollectionTypeName("Edm.String")) .XmlValueRepresentation("<m:element>Foo</m:element><m:element><m:element>0</m:element><m:element>1</m:element></m:element>", EntityModelUtils.GetCollectionTypeName("Edm.String"), null) .WithTypeAnnotation(edmCollectionTypeOfStringType), PayloadEdmModel = edmModel, ExpectedException = ODataExpectedExceptions.ODataException("XmlReaderExtension_InvalidNodeInStringValue", "Element"), }, }; testDescriptors = testDescriptors.Select(td => td.InProperty()); this.CombinatorialEngineProvider.RunCombinations( testDescriptors, this.ReaderTestConfigurationProvider.AtomFormatConfigurations, (testDescriptor, testConfiguration) => { testDescriptor.RunTest(testConfiguration); }); }
/// <summary> /// Creates a test model shared among parameter reader/writer tests. /// </summary> /// <returns>Returns a model with operation imports.</returns> public static IEdmModel BuildModelWithFunctionImport() { EdmCoreModel coreModel = EdmCoreModel.Instance; EdmModel model = new EdmModel(); const string defaultNamespaceName = DefaultNamespaceName; EdmEntityContainer container = new EdmEntityContainer(defaultNamespaceName, "TestContainer"); model.AddElement(container); EdmComplexType complexType = new EdmComplexType(defaultNamespaceName, "ComplexType"); complexType.AddProperty(new EdmStructuralProperty(complexType, "PrimitiveProperty", coreModel.GetString(false))); complexType.AddProperty(new EdmStructuralProperty(complexType, "ComplexProperty", complexType.ToTypeReference(false))); model.AddElement(complexType); EdmEnumType enumType = new EdmEnumType(defaultNamespaceName, "EnumType"); model.AddElement(enumType); EdmEntityType entityType = new EdmEntityType(defaultNamespaceName, "EntityType"); entityType.AddKeys(new IEdmStructuralProperty[] { new EdmStructuralProperty(entityType, "ID", coreModel.GetInt32(false)) }); entityType.AddProperty(new EdmStructuralProperty(entityType, "ComplexProperty", complexType.ToTypeReference())); container.AddFunctionAndFunctionImport(model, "FunctionImport_Primitive", coreModel.GetString(false) /*returnType*/, null /*entitySet*/, false /*composable*/, false /*bindable*/).Function.AsEdmFunction().AddParameter("primitive", coreModel.GetString(false)); container.AddFunctionAndFunctionImport(model, "FunctionImport_NullablePrimitive", coreModel.GetString(false) /*returnType*/, null /*entitySet*/, false /*composable*/, false /*bindable*/).Function.AsEdmFunction().AddParameter("nullablePrimitive", coreModel.GetString(true)); EdmCollectionType stringCollectionType = new EdmCollectionType(coreModel.GetString(true)); container.AddFunctionAndFunctionImport(model, "FunctionImport_PrimitiveCollection", coreModel.GetString(false) /*returnType*/, null /*entitySet*/, false /*composable*/, false /*bindable*/).Function.AsEdmFunction().AddParameter("primitiveCollection", stringCollectionType.ToTypeReference(false)); container.AddFunctionAndFunctionImport(model, "FunctionImport_Complex", coreModel.GetString(false) /*returnType*/, null /*entitySet*/, false /*composable*/, false /*bindable*/).Function.AsEdmFunction().AddParameter("complex", complexType.ToTypeReference(true)); EdmCollectionType complexCollectionType = new EdmCollectionType(complexType.ToTypeReference()); container.AddFunctionAndFunctionImport(model, "FunctionImport_ComplexCollection", coreModel.GetString(false) /*returnType*/, null /*entitySet*/, false /*composable*/, false /*bindable*/).Function.AsEdmFunction().AddParameter("complexCollection", complexCollectionType.ToTypeReference()); container.AddFunctionAndFunctionImport(model, "FunctionImport_Entry", coreModel.GetString(false) /*returnType*/, null /*entitySet*/, false /*composable*/, true /*bindable*/).Function.AsEdmFunction().AddParameter("entry", entityType.ToTypeReference()); EdmCollectionType entityCollectionType = new EdmCollectionType(entityType.ToTypeReference()); container.AddFunctionAndFunctionImport(model, "FunctionImport_Feed", coreModel.GetString(false) /*returnType*/, null /*entitySet*/, false /*composable*/, true /*bindable*/).Function.AsEdmFunction().AddParameter("feed", entityCollectionType.ToTypeReference()); container.AddFunctionAndFunctionImport(model, "FunctionImport_Stream", coreModel.GetString(false) /*returnType*/, null /*entitySet*/, false /*composable*/, false /*bindable*/).Function.AsEdmFunction().AddParameter("stream", coreModel.GetStream(false)); container.AddFunctionAndFunctionImport(model, "FunctionImport_Enum", coreModel.GetString(false) /*returnType*/, null /*entitySet*/, false /*composable*/, false /*bindable*/).Function.AsEdmFunction().AddParameter("enum", enumType.ToTypeReference()); var functionImport_PrimitiveTwoParameters = container.AddFunctionAndFunctionImport(model, "FunctionImport_PrimitiveTwoParameters", coreModel.GetString(false) /*returnType*/, null /*entitySet*/, false /*composable*/, false /*bindable*/); var function_PrimitiveTwoParameters = functionImport_PrimitiveTwoParameters.Function.AsEdmFunction(); function_PrimitiveTwoParameters.AddParameter("p1", coreModel.GetInt32(false)); function_PrimitiveTwoParameters.AddParameter("p2", coreModel.GetString(false)); container.AddFunctionAndFunctionImport(model, "FunctionImport_Int", coreModel.GetString(false) /*returnType*/, null /*entitySet*/, false /*composable*/, false /*bindable*/).Function.AsEdmFunction().AddParameter("p1", coreModel.GetInt32(false)); container.AddFunctionAndFunctionImport(model, "FunctionImport_Double", coreModel.GetString(false) /*returnType*/, null /*entitySet*/, false /*composable*/, false /*bindable*/).Function.AsEdmFunction().AddParameter("p1", coreModel.GetDouble(false)); EdmCollectionType int32CollectionType = new EdmCollectionType(coreModel.GetInt32(false)); container.AddActionAndActionImport(model, "FunctionImport_NonNullablePrimitiveCollection", null /*returnType*/, null /*entitySet*/, false /*bindable*/).Action.AsEdmAction().AddParameter("p1", int32CollectionType.ToTypeReference(false)); EdmComplexType complexType2 = new EdmComplexType(defaultNamespaceName, "ComplexTypeWithNullableProperties"); complexType2.AddProperty(new EdmStructuralProperty(complexType2, "StringProperty", coreModel.GetString(true))); complexType2.AddProperty(new EdmStructuralProperty(complexType2, "IntegerProperty", coreModel.GetInt32(true))); model.AddElement(complexType2); EdmEnumType enumType1 = new EdmEnumType(defaultNamespaceName, "enumType1"); enumType1.AddMember(new EdmEnumMember(enumType1, "enumType1_value1", new EdmEnumMemberValue(6))); model.AddElement(enumType1); var functionImport_MultipleNullableParameters = container.AddFunctionAndFunctionImport(model, "FunctionImport_MultipleNullableParameters", coreModel.GetString(false) /*returnType*/, null /*entitySet*/, false /*composable*/, false /*bindable*/); var function_MultipleNullableParameters = functionImport_MultipleNullableParameters.Function.AsEdmFunction(); function_MultipleNullableParameters.AddParameter("p1", coreModel.GetBinary(true /*isNullable*/)); function_MultipleNullableParameters.AddParameter("p2", coreModel.GetBoolean(true /*isNullable*/)); function_MultipleNullableParameters.AddParameter("p3", coreModel.GetByte(true /*isNullable*/)); function_MultipleNullableParameters.AddParameter("p5", coreModel.GetDateTimeOffset(true /*isNullable*/)); function_MultipleNullableParameters.AddParameter("p6", coreModel.GetDecimal(true /*isNullable*/)); function_MultipleNullableParameters.AddParameter("p7", coreModel.GetDouble(true /*isNullable*/)); function_MultipleNullableParameters.AddParameter("p8", coreModel.GetGuid(true /*isNullable*/)); function_MultipleNullableParameters.AddParameter("p9", coreModel.GetInt16(true /*isNullable*/)); function_MultipleNullableParameters.AddParameter("p10", coreModel.GetInt32(true /*isNullable*/)); function_MultipleNullableParameters.AddParameter("p11", coreModel.GetInt64(true /*isNullable*/)); function_MultipleNullableParameters.AddParameter("p12", coreModel.GetSByte(true /*isNullable*/)); function_MultipleNullableParameters.AddParameter("p13", coreModel.GetSingle(true /*isNullable*/)); function_MultipleNullableParameters.AddParameter("p14", coreModel.GetSpatial(EdmPrimitiveTypeKind.GeographyPoint, true /*isNullable*/)); function_MultipleNullableParameters.AddParameter("p15", coreModel.GetString(true /*isNullable*/)); function_MultipleNullableParameters.AddParameter("p16", complexType2.ToTypeReference(true /*isNullable*/)); function_MultipleNullableParameters.AddParameter("p17", enumType1.ToTypeReference(true /*isNullable*/)); return(model); }
internal static IEdmCollectionTypeReference ToCollectionTypeReference(this IEdmPrimitiveTypeReference itemTypeReference) { IEdmCollectionType type = new EdmCollectionType(itemTypeReference); return((IEdmCollectionTypeReference)type.ToTypeReference()); }
/// <summary> /// Gets the edm model. Constructs it if it doesn't exist /// </summary> /// <returns>Edm model</param> public IEdmModel GetModel() { if (this.model == null) { ConstructableMetadata metadata = new ConstructableMetadata("InMemoryEntities", "Microsoft.Test.Taupo.OData.WCFService"); IEdmComplexType addressType = metadata.AddComplexType("Address", typeof(Address), null, false); metadata.AddPrimitiveProperty(addressType, "Street", typeof(string)); metadata.AddPrimitiveProperty(addressType, "City", typeof(string)); metadata.AddPrimitiveProperty(addressType, "PostalCode", typeof(string)); IEdmComplexType homeAddressType = metadata.AddComplexType("HomeAddress", typeof(HomeAddress), addressType, false); metadata.AddPrimitiveProperty(homeAddressType, "HomeNO", typeof(string)); IEdmEntityType personType = metadata.AddEntityType("Person", typeof(Person), null, false, "Microsoft.Test.Taupo.OData.WCFService"); metadata.AddKeyProperty(personType, "PersonID", typeof(Int32)); metadata.AddPrimitiveProperty(personType, "FirstName", typeof(string)); metadata.AddPrimitiveProperty(personType, "LastName", typeof(string)); metadata.AddComplexProperty(personType, "HomeAddress", addressType); metadata.AddPrimitiveProperty(personType, "Home", typeof(GeographyPoint)); metadata.AddMultiValueProperty(personType, "Numbers", typeof(string)); metadata.AddContainedResourceSetReferenceProperty(personType, "Brother", personType); metadata.AddContainedResourceReferenceProperty(personType, "Child", personType); var peopleset = metadata.AddEntitySet("People", personType); var specialPerson = metadata.AddSingleton("SpecialPerson", personType); IEdmEntityType customerType = metadata.AddEntityType("Customer", typeof(Customer), personType, false, "Microsoft.Test.Taupo.OData.WCFService"); metadata.AddPrimitiveProperty(customerType, "City", typeof(string)); metadata.AddPrimitiveProperty(customerType, "Birthday", typeof(DateTimeOffset)); metadata.AddPrimitiveProperty(customerType, "TimeBetweenLastTwoOrders", typeof(TimeSpan)); var customerset = metadata.AddEntitySet("Customers", customerType); var vipCustomer = metadata.AddSingleton("VipCustomer", customerType); IEdmEntityType employeeType = metadata.AddEntityType("Employee", typeof(Employee), personType, false, "Microsoft.Test.Taupo.OData.WCFService", true); metadata.AddPrimitiveProperty(employeeType, "DateHired", typeof(DateTimeOffset)); metadata.AddPrimitiveProperty(employeeType, "Office", typeof(GeographyPoint)); var employeeset = metadata.AddEntitySet("Employees", employeeType); var boss = metadata.AddSingleton("Boss", employeeType); IEdmEntityType productType = metadata.AddEntityType("Product", typeof(Product), null, false, "Microsoft.Test.Taupo.OData.WCFService"); metadata.AddKeyProperty(productType, "ProductID", typeof(Int32)); metadata.AddPrimitiveProperty(productType, "Name", typeof(string)); metadata.AddPrimitiveProperty(productType, "QuantityPerUnit", typeof(string)); metadata.AddPrimitiveProperty(productType, "UnitPrice", typeof(float)); metadata.AddPrimitiveProperty(productType, "QuantityInStock", typeof(Int32)); metadata.AddPrimitiveProperty(productType, "Discontinued", typeof(bool)); metadata.AddComplexProperty(productType, "ManufactureAddresss", addressType, true); var productset = metadata.AddEntitySet("Products", productType); var specialProduct = metadata.AddSingleton("SpecialProduct", productType); IEdmEntityType orderType = metadata.AddEntityType("Order", typeof(Order), null, false, "Microsoft.Test.Taupo.OData.WCFService"); var orderset = metadata.AddEntitySet("Orders", orderType); metadata.AddKeyProperty(orderType, "OrderID", typeof(Int32)); metadata.AddPrimitiveProperty(orderType, "CustomerID", typeof(Int32)); metadata.AddPrimitiveProperty(orderType, "EmployeeID", typeof(Int32?)); metadata.AddPrimitiveProperty(orderType, "OrderDate", typeof(DateTimeOffset)); metadata.AddResourceReferenceProperty(orderType, "LoggedInEmployee", employeeset, null); metadata.AddResourceReferenceProperty(orderType, "CustomerForOrder", customerset, null); var specialOrder = metadata.AddSingleton("SpecialOrder", orderType); metadata.AddContainedResourceReferenceProperty(personType, "FirstOrder", orderType); IEdmEntityType orderDetailType = metadata.AddEntityType("OrderDetail", typeof(OrderDetail), null, false, "Microsoft.Test.Taupo.OData.WCFService"); metadata.AddKeyProperty(orderDetailType, "OrderID", typeof(Int32)); metadata.AddKeyProperty(orderDetailType, "ProductID", typeof(Int32)); metadata.AddPrimitiveProperty(orderDetailType, "OrderPlaced", typeof(DateTimeOffset)); metadata.AddPrimitiveProperty(orderDetailType, "Quantity", typeof(Int32)); metadata.AddPrimitiveProperty(orderDetailType, "UnitPrice", typeof(float)); var productOrderedNavigation = metadata.AddResourceReferenceProperty(orderDetailType, "ProductOrdered", productset, null); var associatedOrderNavigation = metadata.AddResourceReferenceProperty(orderDetailType, "AssociatedOrder", orderset, null); var orderdetailsSet = metadata.AddEntitySet("OrderDetails", orderDetailType); // Edm.Duration IEdmEntityType durationInKeyType = metadata.AddEntityType("DurationInKey", typeof(DurationInKey), null, false, "Microsoft.Test.Taupo.OData.WCFService"); metadata.AddKeyProperty(durationInKeyType, "Id", typeof(TimeSpan)); metadata.AddEntitySet("DurationInKeys", durationInKeyType); // FUNCTIONS // Function that binds to single order metadata.AddFunctionAndFunctionImport("GetOrderRate", orderType.ToTypeReference(), MetadataUtils.GetPrimitiveTypeReference(typeof(Int32)), null, true); //Function that binds to a single order and returns a single order metadata.AddFunction("GetNextOrder", orderType.ToTypeReference(), orderType.ToTypeReference(), true, new EdmPathExpression("bindingparameter"), true); // Function that returns a set of orders var collectionOrders = new EdmCollectionType(orderType.ToTypeReference()).ToTypeReference(); metadata.AddFunction("OrdersWithMoreThanTwoItems", collectionOrders, collectionOrders, true, new EdmPathExpression("bindingparameter"), true /*iscomposable*/); var overload1Function = metadata.AddFunction("OrdersWithMoreThanTwoItems", collectionOrders, collectionOrders, true, new EdmPathExpression("bindingparameter"), true /*iscomposable*/); overload1Function.AddParameter("IntParameter", MetadataUtils.GetPrimitiveTypeReference(typeof(Int32))); var overload2Function = metadata.AddFunction("OrdersWithMoreThanTwoItems", collectionOrders, collectionOrders, true, new EdmPathExpression("bindingparameter"), true /*iscomposable*/); overload2Function.AddParameter("IntParameter", MetadataUtils.GetPrimitiveTypeReference(typeof(Int32))); overload2Function.AddParameter("EntityParameter", productType.ToTypeReference()); var collectionCustomers = new EdmCollectionType(customerType.ToTypeReference()).ToTypeReference(); var customersInCityFunction = metadata.AddFunction("InCity", collectionCustomers, collectionCustomers, true, new EdmPathExpression("bindingparameter"), true /*iscomposable*/); customersInCityFunction.AddParameter("City", MetadataUtils.GetPrimitiveTypeReference(typeof(String))); var customersWithinFunction = metadata.AddFunction("Within", collectionCustomers, collectionCustomers, true, new EdmPathExpression("bindingparameter"), true /*iscomposable*/); customersWithinFunction.AddParameter("Location", MetadataUtils.GetPrimitiveTypeReference(typeof(GeographyPoint))); customersWithinFunction.AddParameter("Address", addressType.ToTypeReference(true /*nullable*/)); customersWithinFunction.AddParameter("Distance", MetadataUtils.GetPrimitiveTypeReference(typeof(Double))); customersWithinFunction.AddParameter("ArbitraryInt", MetadataUtils.GetPrimitiveTypeReference(typeof(Int32))); customersWithinFunction.AddParameter("DateTimeOffset", MetadataUtils.GetPrimitiveTypeReference(typeof(DateTimeOffset?))); customersWithinFunction.AddParameter("Byte", MetadataUtils.GetPrimitiveTypeReference(typeof(Byte))); customersWithinFunction.AddParameter("LineString", MetadataUtils.GetPrimitiveTypeReference(typeof(GeometryLineString))); var withinFunction = metadata.AddFunction("Within", customerType.ToTypeReference(), MetadataUtils.GetPrimitiveTypeReference(typeof(bool)), true, null, true /*iscomposable*/); withinFunction.AddParameter("Location", addressType.ToTypeReference()); withinFunction.AddParameter("Distance", MetadataUtils.GetPrimitiveTypeReference(typeof(Int32))); var withinFunction2 = metadata.AddFunction("Within", customerType.ToTypeReference(), MetadataUtils.GetPrimitiveTypeReference(typeof(bool)), true, null, true /*iscomposable*/); withinFunction2.AddParameter("Distance", MetadataUtils.GetPrimitiveTypeReference(typeof(Int32))); metadata.AddFunction("GetChild", personType.ToTypeReference(), personType.ToTypeReference(), true, new EdmPathExpression("bindingparameter/Child"), true /*iscomposable*/); metadata.AddAction("GetBrothers", personType.ToTypeReference(), new EdmCollectionTypeReference(new EdmCollectionType(personType.ToTypeReference())), true, new EdmPathExpression("bindingparameter/Child")); //Unbound Functions var lotsofOrders = metadata.AddFunctionAndFunctionImport("HasLotsOfOrders", null, MetadataUtils.GetPrimitiveTypeReference(typeof(bool)), null, false /*isBindable*/); lotsofOrders.Function.AsEdmFunction().AddParameter("Person", personType.ToTypeReference()); metadata.AddFunctionAndFunctionImport("HowManyPotatoesEaten", null, MetadataUtils.GetPrimitiveTypeReference(typeof(Int32)), null, false); metadata.AddFunctionAndFunctionImport("QuoteOfTheDay", null, MetadataUtils.GetPrimitiveTypeReference(typeof(string)), null, false); // ACTIONS var action1 = metadata.AddAction("ChangeAddress", personType.ToTypeReference(), null /*returnType*/, true /*isbound*/, null /*entitySetPathExpression*/); action1.AddParameter(new EdmOperationParameter(action1, "Street", MetadataUtils.GetPrimitiveTypeReference(typeof(string)))); action1.AddParameter(new EdmOperationParameter(action1, "City", MetadataUtils.GetPrimitiveTypeReference(typeof(string)))); action1.AddParameter(new EdmOperationParameter(action1, "PostalCode", MetadataUtils.GetPrimitiveTypeReference(typeof(string)))); metadata.AddActionImport("ChangeAddress", action1, null /*entitySet*/); // Unbound action with no parameters var getRecentCustomersAction = metadata.AddAction("GetRecentCustomers", null /*boundType*/, new EdmCollectionTypeReference(new EdmCollectionType(orderType.ToTypeReference())), false /*isbound*/, null /*entitySetPathExpression*/); metadata.AddActionImport("GetRecentCustomers", getRecentCustomersAction, orderset); //Adding order details navigation property to order. var orderDetailNavigation = metadata.AddResourceSetReferenceProperty(orderType, "OrderDetails", orderdetailsSet, null); //Adding orders navigation to Customer. var ordersNavigation = metadata.AddResourceSetReferenceProperty(customerType, "Orders", orderset, null); ((EdmEntitySet)customerset).AddNavigationTarget(ordersNavigation, orderset); //Adding parent navigation to person metadata.AddResourceSetReferenceProperty(personType, "Parent", null, personType); //Since the people set can contain a customer we need to include the target for that navigation in the people set. ((EdmEntitySet)peopleset).AddNavigationTarget(ordersNavigation, orderset); //Since the OrderSet can contain a OrderDetail we need to include the target for that navigation in the order set. ((EdmEntitySet)orderset).AddNavigationTarget(orderDetailNavigation, orderdetailsSet); //Since the OrderDetailSet can contain a AssociatedOrder we need to include the target for that navigation in the orderdetail set. ((EdmEntitySet)orderdetailsSet).AddNavigationTarget(associatedOrderNavigation, orderset); //Since the OrderDetailSet can contain a ProductOrdered we need to include the target for that navigation in the orderdetail set. ((EdmEntitySet)orderdetailsSet).AddNavigationTarget(productOrderedNavigation, productset); ((EdmSingleton)specialOrder).AddNavigationTarget(orderDetailNavigation, orderdetailsSet); ((EdmSingleton)specialPerson).AddNavigationTarget(ordersNavigation, orderset); this.model = metadata; } return(this.model); }
/// <summary> /// Combines the property types and returns a reference to the resulting facade. /// </summary> /// <param name="propertyName">The name of the navigation properties being combined. Used only for error messages.</param> /// <param name="clientProperty">The client property.</param> /// <param name="serverProperty">The server property.</param> /// <param name="modelFacade">The model facade.</param> /// <returns> /// A type reference to the combined type. /// </returns> private static IEdmTypeReference CombinePropertyTypes(string propertyName, IEdmNavigationProperty clientProperty, IEdmNavigationProperty serverProperty, EdmModelFacade modelFacade) { Debug.Assert(clientProperty != null, "clientProperty != null"); Debug.Assert(serverProperty != null, "serverProperty != null"); IEdmTypeReference clientPropertyType = clientProperty.Type; IEdmTypeReference serverPropertyType = serverProperty.Type; // ensure that either both sides are a collection or neither is. IEdmCollectionTypeReference clientCollectionType = clientPropertyType as IEdmCollectionTypeReference; IEdmCollectionTypeReference serverCollectionType = serverPropertyType as IEdmCollectionTypeReference; bool isCollection = clientCollectionType != null; if (isCollection != (serverCollectionType != null)) { throw new InvalidOperationException(ErrorStrings.EdmNavigationPropertyFacade_InconsistentMultiplicity(propertyName)); } // For collection properties: extract the element types, combine them, then recreate the collection. // For reference properties: get the entity types and combine them. IEdmType combinedType; if (isCollection) { // get the client element type and ensure it's an entity type. IEdmEntityTypeReference clientElementTypeReference = clientCollectionType.ElementType() as IEdmEntityTypeReference; if (clientElementTypeReference == null) { throw new InvalidOperationException(ErrorStrings.EdmNavigationPropertyFacade_NonEntityType(propertyName, clientProperty.DeclaringType.FullName())); } // get the server element type and ensure it's an entity type. IEdmEntityTypeReference serverElementTypeReference = serverCollectionType.ElementType() as IEdmEntityTypeReference; if (serverElementTypeReference == null) { throw new InvalidOperationException(ErrorStrings.EdmNavigationPropertyFacade_NonEntityType(propertyName, serverProperty.DeclaringType.FullName())); } // combine the element types. combinedType = modelFacade.CombineWithServerType(clientElementTypeReference.EntityDefinition(), serverElementTypeReference.EntityDefinition()); // turn it back into a collection, maintaining nullability of the client's element type. combinedType = new EdmCollectionType(combinedType.ToEdmTypeReference(clientElementTypeReference.IsNullable)); } else { // ensure the server property type is an entity type. IEdmEntityTypeReference clientEntityTypeReference = clientPropertyType as IEdmEntityTypeReference; if (clientEntityTypeReference == null) { throw new InvalidOperationException(ErrorStrings.EdmNavigationPropertyFacade_NonEntityType(propertyName, clientProperty.DeclaringType.FullName())); } // ensure the server property type is an entity type. IEdmEntityTypeReference serverEntityTypeReference = serverPropertyType as IEdmEntityTypeReference; if (serverEntityTypeReference == null) { throw new InvalidOperationException(ErrorStrings.EdmNavigationPropertyFacade_NonEntityType(propertyName, serverProperty.DeclaringType.FullName())); } combinedType = modelFacade.CombineWithServerType(clientEntityTypeReference.EntityDefinition(), serverEntityTypeReference.EntityDefinition()); } // return a type reference, maintaining the original nullability from the client property type. return(combinedType.ToEdmTypeReference(clientPropertyType.IsNullable)); }