예제 #1
0
        private static Microsoft.OData.UriParser.ODataPath GeneratePath(IEdmNavigationSource navigationSource)
        {
            Contract.Assert(navigationSource != null);

            switch (navigationSource.NavigationSourceKind())
            {
            case EdmNavigationSourceKind.EntitySet:
                return(new Microsoft.OData.UriParser.ODataPath(new EntitySetSegment((IEdmEntitySet)navigationSource)));

            case EdmNavigationSourceKind.Singleton:
                return(new Microsoft.OData.UriParser.ODataPath(new SingletonSegment((IEdmSingleton)navigationSource)));

            case EdmNavigationSourceKind.ContainedEntitySet:
                IEdmContainedEntitySet containedEntitySet    = (IEdmContainedEntitySet)navigationSource;
                Microsoft.OData.UriParser.ODataPath path     = GeneratePath(containedEntitySet.ParentNavigationSource);
                IList <ODataPathSegment>            segments = new List <ODataPathSegment>();
                foreach (var item in path)
                {
                    segments.Add(item);
                }

                segments.Add(new NavigationPropertySegment(containedEntitySet.NavigationProperty, containedEntitySet.ParentNavigationSource));
                return(new Microsoft.OData.UriParser.ODataPath(segments));

            case EdmNavigationSourceKind.None:
            case EdmNavigationSourceKind.UnknownEntitySet:
            default:
                return(null);
            }
        }
            /// <summary>
            /// Constructs an instance of <see cref="ODataFeedAndEntryTypeContext"/>.
            /// </summary>
            /// <param name="navigationSource">The navigation source of the feed or entry.</param>
            /// <param name="navigationSourceEntityType">The entity type of the navigation source.</param>
            /// <param name="expectedEntityType">The expected entity type of the feed or entry.</param>
            /// <param name="model">The Edm model instance to use.</param>
            internal ODataFeedAndEntryTypeContextWithModel(IEdmNavigationSource navigationSource, IEdmEntityType navigationSourceEntityType, IEdmEntityType expectedEntityType, IEdmModel model)
                : base(/*throwIfMissingTypeInfo*/ false)
            {
                Debug.Assert(model != null, "model != null");
                Debug.Assert(navigationSource != null, "navigationSource != null");
                Debug.Assert(navigationSourceEntityType != null, "navigationSourceEntityType != null");
                Debug.Assert(expectedEntityType != null, "expectedEntityType != null");

                this.navigationSource           = navigationSource;
                this.navigationSourceEntityType = navigationSourceEntityType;
                this.expectedEntityType         = expectedEntityType;
                this.model = model;

                IEdmContainedEntitySet containedEntitySet = navigationSource as IEdmContainedEntitySet;

                if (containedEntitySet != null)
                {
                    if (containedEntitySet.NavigationProperty.Type.TypeKind() == EdmTypeKind.Collection)
                    {
                        this.isFromCollection = true;
                    }
                }

                this.navigationSourceName = this.navigationSource.Name;
                this.isMediaLinkEntry     = this.expectedEntityType.HasStream;
                this.lazyUrlConvention    = new SimpleLazy <UrlConvention>(() => UrlConvention.ForModel(this.model));
            }
예제 #3
0
        public static IEnumerable <IEdmStructuralProperty> GetConcurrencyProperties(this IEdmModel model, IEdmNavigationSource navigationSource)
        {
            Contract.Assert(model != null);
            Contract.Assert(navigationSource != null);

            IEnumerable <IEdmStructuralProperty> cachedProperties;

            if (_concurrencyProperties != null && _concurrencyProperties.TryGetValue(navigationSource, out cachedProperties))
            {
                return(cachedProperties);
            }

            IList <IEdmStructuralProperty> results = new List <IEdmStructuralProperty>();
            IEdmEntityType            entityType   = navigationSource.EntityType();
            IEdmVocabularyAnnotatable annotatable  = navigationSource as IEdmVocabularyAnnotatable;

            IEdmContainedEntitySet navigationSourceAsEntitySet = navigationSource as IEdmContainedEntitySet;

            if (navigationSourceAsEntitySet != null)
            {
                annotatable = navigationSourceAsEntitySet.NavigationProperty as EdmNavigationProperty;
            }

            if (annotatable != null)
            {
                IEdmValueAnnotation annotation = model.FindVocabularyAnnotations <IEdmValueAnnotation>(annotatable, CoreVocabularyModel.ConcurrencyTerm).FirstOrDefault();
                if (annotation != null)
                {
                    IEdmCollectionExpression properties = annotation.Value as IEdmCollectionExpression;
                    if (properties != null)
                    {
                        foreach (var property in properties.Elements)
                        {
                            IEdmPathExpression pathExpression = property as IEdmPathExpression;
                            if (pathExpression != null)
                            {
                                // So far, we only consider the single path, because only the direct properties from declaring type are used.
                                // However we have an issue tracking on: https://github.com/OData/WebApi/issues/472
                                string                 propertyName       = pathExpression.Path.Single();
                                IEdmProperty           edmProperty        = entityType.FindProperty(propertyName);
                                IEdmStructuralProperty structuralProperty = edmProperty as IEdmStructuralProperty;
                                if (structuralProperty != null)
                                {
                                    results.Add(structuralProperty);
                                }
                            }
                        }
                    }
                }
            }

            if (_concurrencyProperties == null)
            {
                _concurrencyProperties = new ConcurrentDictionary <IEdmNavigationSource, IEnumerable <IEdmStructuralProperty> >();
            }

            _concurrencyProperties[navigationSource] = results;
            return(results);
        }
예제 #4
0
        public UriParserTestsBase()
        {
            this.model           = new InMemoryModel().GetModel();
            this.customerType    = this.model.FindType("Microsoft.Test.Taupo.OData.WCFService.Customer");
            this.personType      = this.model.FindType("Microsoft.Test.Taupo.OData.WCFService.Person");
            this.employeeType    = this.model.FindType("Microsoft.Test.Taupo.OData.WCFService.Employee");
            this.productType     = this.model.FindType("Microsoft.Test.Taupo.OData.WCFService.Product");
            this.orderType       = this.model.FindType("Microsoft.Test.Taupo.OData.WCFService.Order");
            this.orderDetailType = this.model.FindType("Microsoft.Test.Taupo.OData.WCFService.OrderDetail");

            this.defaultContainer = this.model.FindEntityContainer("InMemoryEntities");
            this.peopleSet        = this.defaultContainer.FindEntitySet("People");
            this.customerSet      = this.defaultContainer.FindEntitySet("Customers");
            this.employeeSet      = this.defaultContainer.FindEntitySet("Employees");
            this.productSet       = this.defaultContainer.FindEntitySet("Products");
            this.orderSet         = this.defaultContainer.FindEntitySet("Orders");
            this.orderDetailSet   = this.defaultContainer.FindEntitySet("OrderDetails");

            this.boss           = this.defaultContainer.FindSingleton("Boss");
            this.specialOrder   = this.defaultContainer.FindSingleton("SpecialOrder");
            this.vipCustomer    = this.defaultContainer.FindSingleton("VipCustomer");
            this.specialProduct = this.defaultContainer.FindSingleton("SpecialProduct");

            IEdmNavigationProperty childNavigationProperty = ((IEdmEntityType)this.personType).FindProperty("Child") as IEdmNavigationProperty;

            this.childSet = peopleSet.FindNavigationTarget(childNavigationProperty) as IEdmContainedEntitySet;
            IEdmNavigationProperty brotherNavigationProperty = ((IEdmEntityType)this.personType).FindProperty("Brother") as IEdmNavigationProperty;

            this.brotherSet = peopleSet.FindNavigationTarget(brotherNavigationProperty) as IEdmContainedEntitySet;

            this.customer    = (IEdmEntityType)customerType;
            this.person      = (IEdmEntityType)personType;
            this.employee    = (IEdmEntityType)employeeType;
            this.product     = (IEdmEntityType)productType;
            this.order       = (IEdmEntityType)orderType;
            this.orderDetail = (IEdmEntityType)orderDetailType;

            this.serviceRoot        = new Uri("http://www.potato.com/");
            this.productBase        = new Uri("http://www.potato.com/Products/");
            this.employeeBase       = new Uri("http://www.potato.com/Employees/");
            this.customerBase       = new Uri("http://www.potato.com/Customers/");
            this.peopleBase         = new Uri("http://www.potato.com/People/");
            this.numbersBase        = new Uri("http://www.potato.com/People(1)/Numbers");
            this.orderBase          = new Uri("http://www.potato.com/Orders/");
            this.orderDetailBase    = new Uri("http://www.potato.com/OrderDetails/");
            this.bossBase           = new Uri("http://www.potato.com/Boss/");
            this.specialOrderBase   = new Uri("http://www.potato.com/SpecialOrder");
            this.specialProductBase = new Uri("http://www.potato.com/SpecialProduct");
            this.vipCustomerBase    = new Uri("http://www.potato.com/VipCustomer");
            this.specialPersonBase  = new Uri("http://www.potato.com/SpecialPerson");
            this.durationInKeysBase = new Uri("http://www.potato.com/DurationInKeys");
        }
예제 #5
0
        public void GenerateNavigationLink_WorksToGenerateExpectedNavigationLink_ForContainedNavigation(
            bool includeCast,
            string expectedNavigationLink)
        {
            // NOTE: This test is generating a link that does not technically correspond to a valid model (specifically
            //       the extra OrderLines navigation), but it allows us to validate the nested navigation scenario
            //       without twisting the model unnecessarily.

            // Arrange
            IEdmEntityType myOrder   = (IEdmEntityType)_myOrderModel.FindDeclaredType("NS.MyOrder");
            IEdmEntityType orderLine = (IEdmEntityType)_myOrderModel.FindDeclaredType("NS.OrderLine");

            IEdmNavigationProperty orderLinesProperty = myOrder.NavigationProperties().Single(x => x.ContainsTarget);

            IEdmEntitySet entitySet = _myOrderModel.FindDeclaredEntitySet("MyOrders");
            IDictionary <string, object> parameters = new Dictionary <string, object>
            {
                { "ID", 42 }
            };

            IDictionary <string, object> parameters2 = new Dictionary <string, object>
            {
                { "ID", 21 }
            };

            // containment
            IEdmContainedEntitySet orderLines = (IEdmContainedEntitySet)entitySet.FindNavigationTarget(orderLinesProperty);

            ODataPath path = new ODataPath(
                new EntitySetSegment(entitySet),
                new KeySegment(parameters.ToArray(), myOrder, entitySet),
                new NavigationPropertySegment(orderLinesProperty, orderLines),
                new KeySegment(parameters2.ToArray(), orderLine, orderLines));

            var request           = RequestFactory.Create(_myOrderModel);
            var serializerContext = ODataSerializerContextFactory.Create(_myOrderModel, orderLines, path, request);
            var entityContext     = new ResourceContext(serializerContext, orderLine.AsReference(), new { ID = 21 });

            // Act
            Uri uri = entityContext.GenerateNavigationPropertyLink(orderLinesProperty, includeCast);

            // Assert
            Assert.Equal(expectedNavigationLink, uri.AbsoluteUri);
        }
        public void TestInitialize()
        {
            this.testModel = Test.OData.Utils.Metadata.TestModels.BuildTestModel();

            this.defaultContainer = this.testModel.EntityContainer;

            this.personSet = this.defaultContainer.FindEntitySet("Persons");
            this.personType = (IEdmEntityType)this.testModel.FindType("TestModel.Person");
            this.employeeType = (IEdmEntityType)this.testModel.FindType("TestModel.Employee");
            this.officeType = (IEdmEntityType)this.testModel.FindType("TestModel.OfficeType");
            this.addressType = (IEdmComplexType)this.testModel.FindType("TestModel.Address");
            this.metropolitanCitySet = this.defaultContainer.FindEntitySet("MetropolitanCities");
            this.metropolitanCityType = (IEdmEntityType)this.testModel.FindType("TestModel.MetropolitanCityType");
            this.boss = this.defaultContainer.FindSingleton("Boss");
            this.containedOfficeNavigationProperty = (IEdmNavigationProperty)this.metropolitanCityType.FindProperty("ContainedOffice");
            this.containedOfficeSet = (IEdmContainedEntitySet)metropolitanCitySet.FindNavigationTarget(this.containedOfficeNavigationProperty);
            this.containedMetropolitanCityNavigationProperty = (IEdmNavigationProperty)this.officeType.FindProperty("ContainedCity");
            this.containedMetropolitanCitySet = (IEdmContainedEntitySet)containedOfficeSet.FindNavigationTarget(this.containedMetropolitanCityNavigationProperty);
        }
        public void TestInitialize()
        {
            this.testModel = Test.OData.Utils.Metadata.TestModels.BuildTestModel();

            this.defaultContainer = this.testModel.EntityContainer;

            this.personSet            = this.defaultContainer.FindEntitySet("Persons");
            this.personType           = (IEdmEntityType)this.testModel.FindType("TestModel.Person");
            this.employeeType         = (IEdmEntityType)this.testModel.FindType("TestModel.Employee");
            this.officeType           = (IEdmEntityType)this.testModel.FindType("TestModel.OfficeType");
            this.addressType          = (IEdmComplexType)this.testModel.FindType("TestModel.Address");
            this.metropolitanCitySet  = this.defaultContainer.FindEntitySet("MetropolitanCities");
            this.metropolitanCityType = (IEdmEntityType)this.testModel.FindType("TestModel.MetropolitanCityType");
            this.boss = this.defaultContainer.FindSingleton("Boss");
            this.containedOfficeNavigationProperty = (IEdmNavigationProperty)this.metropolitanCityType.FindProperty("ContainedOffice");
            this.containedOfficeSet = (IEdmContainedEntitySet)metropolitanCitySet.FindNavigationTarget(this.containedOfficeNavigationProperty);
            this.containedMetropolitanCityNavigationProperty = (IEdmNavigationProperty)this.officeType.FindProperty("ContainedCity");
            this.containedMetropolitanCitySet = (IEdmContainedEntitySet)containedOfficeSet.FindNavigationTarget(this.containedMetropolitanCityNavigationProperty);
        }
예제 #8
0
        internal override void WriteNavigationPropertyBinding(IEdmNavigationPropertyBinding binding)
        {
            this.xmlWriter.WriteStartElement(CsdlConstants.Element_NavigationPropertyBinding);

            this.WriteRequiredAttribute(CsdlConstants.Attribute_Path, binding.Path.Path, EdmValueWriter.StringAsXml);

            // TODO: handle container names, etc.
            IEdmContainedEntitySet containedEntitySet = binding.Target as IEdmContainedEntitySet;

            if (containedEntitySet != null)
            {
                this.WriteRequiredAttribute(CsdlConstants.Attribute_Target, containedEntitySet.Path.Path, EdmValueWriter.StringAsXml);
            }
            else
            {
                this.WriteRequiredAttribute(CsdlConstants.Attribute_Target, binding.Target.Name, EdmValueWriter.StringAsXml);
            }

            this.xmlWriter.WriteEndElement();
        }
예제 #9
0
        /// <summary>
        /// Finds the bindings of the navigation property.
        /// </summary>
        /// <param name="navigationProperty">The navigation property.</param>
        /// <returns>The list of bindings for current navigation property.</returns>
        public override IEnumerable <IEdmNavigationPropertyBinding> FindNavigationPropertyBindings(IEdmNavigationProperty navigationProperty)
        {
            IEnumerable <IEdmNavigationPropertyBinding> bindings = base.FindNavigationPropertyBindings(navigationProperty);
            IEdmNavigationSource   parent;
            IEdmContainedEntitySet contained = this;
            IEnumerable <IEdmNavigationPropertyBinding> parentBindings;

            while (contained != null)
            {
                parent         = contained.ParentNavigationSource;
                parentBindings = parent.FindNavigationPropertyBindings(navigationProperty);
                if (parentBindings != null)
                {
                    bindings = bindings == null ? parentBindings : bindings.Concat(parentBindings);
                }

                contained = parent as IEdmContainedEntitySet;
            }

            return(bindings);
        }
예제 #10
0
        public void GenerateNavigationLink_WorksToGenerateExpectedNavigationLink_ForNonContainedNavigation()
        {
            // Arrange
            IEdmEntityType         myOrder               = (IEdmEntityType)_myOrderModel.FindDeclaredType("NS.MyOrder");
            IEdmEntityType         orderLine             = (IEdmEntityType)_myOrderModel.FindDeclaredType("NS.OrderLine");
            IEdmNavigationProperty nonOrderLinesProperty = myOrder.NavigationProperties().Single(x => x.Name.Equals("NonContainedOrderLines"));

            IEdmEntitySet entitySet = _myOrderModel.FindDeclaredEntitySet("MyOrders");
            IDictionary <string, object> parameters = new Dictionary <string, object>
            {
                { "ID", 42 }
            };

            IDictionary <string, object> parameters2 = new Dictionary <string, object>
            {
                { "ID", 21 }
            };

            IEdmNavigationSource nonContainedOrderLines = entitySet.FindNavigationTarget(nonOrderLinesProperty);
            ODataPath            path = new ODataPath(
                new EntitySetSegment(entitySet),
                new KeySegment(parameters.ToArray(), myOrder, entitySet),
                new NavigationPropertySegment(nonOrderLinesProperty, nonContainedOrderLines),
                new KeySegment(parameters2.ToArray(), orderLine, nonContainedOrderLines));

            IEdmNavigationProperty orderLinesProperty = myOrder.NavigationProperties().Single(x => x.ContainsTarget);
            IEdmContainedEntitySet orderLines         = (IEdmContainedEntitySet)entitySet.FindNavigationTarget(orderLinesProperty);

            var request           = RequestFactory.Create(_myOrderModel);
            var serializerContext = ODataSerializerContextFactory.Create(_myOrderModel, orderLines, path, request);
            var entityContext     = new ResourceContext(serializerContext, orderLine.AsReference(), new { ID = 21 });

            // Act
            Uri uri = entityContext.GenerateSelfLink(false);

            // Assert
            Assert.Equal("http://localhost/OrderLines(21)", uri.AbsoluteUri);
        }
예제 #11
0
            /// <summary>
            /// Constructs an instance of <see cref="ODataResourceTypeContext"/>.
            /// </summary>
            /// <param name="navigationSource">The navigation source of the resource set or resource.</param>
            /// <param name="navigationSourceEntityType">The entity type of the navigation source.</param>
            /// <param name="expectedResourceType">The expected resource type of the resource set or resource.</param>
            internal ODataResourceTypeContextWithModel(IEdmNavigationSource navigationSource, IEdmEntityType navigationSourceEntityType, IEdmStructuredType expectedResourceType)
                : base(expectedResourceType, /*throwIfMissingTypeInfo*/ false)
            {
                Debug.Assert(expectedResourceType != null, "expectedResourceType != null");
                Debug.Assert(navigationSource != null &&
                             navigationSourceEntityType != null ||
                             expectedResourceType.IsODataComplexTypeKind(),
                             "navigationSource != null && navigationSourceEntityType != null || expectedResourceType.IsODataComplexTypeKind()");

                this.navigationSource           = navigationSource;
                this.navigationSourceEntityType = navigationSourceEntityType;

                IEdmContainedEntitySet containedEntitySet = navigationSource as IEdmContainedEntitySet;

                if (containedEntitySet != null)
                {
                    if (containedEntitySet.NavigationProperty.Type.TypeKind() == EdmTypeKind.Collection)
                    {
                        this.isFromCollection = true;
                    }
                }

                IEdmUnknownEntitySet unknownEntitySet = navigationSource as IEdmUnknownEntitySet;

                if (unknownEntitySet != null)
                {
                    if (unknownEntitySet.Type.TypeKind == EdmTypeKind.Collection)
                    {
                        this.isFromCollection = true;
                    }
                }

                this.navigationSourceName = this.navigationSource == null ? null : this.navigationSource.Name;
                var entityType = this.expectedResourceType as IEdmEntityType;

                this.isMediaLinkEntry = entityType == null ? false : entityType.HasStream;
            }
예제 #12
0
        private static void GenerateBaseODataPathSegmentsForNonSingletons(
            ODataPath path,
            IEdmNavigationSource navigationSource,
            IList <ODataPathSegment> odataPath)
        {
            // If the navigation is not a singleton we need to walk all of the path segments to generate a
            // contextually accurate URI.
            bool segmentFound   = false;
            bool containedFound = false;

            if (path != null)
            {
                var segments = path.Segments;
                int length   = segments.Count;
                int previousNavigationPathIndex = -1;
                for (int i = 0; i < length; i++)
                {
                    ODataPathSegment     pathSegment             = segments[i];
                    IEdmNavigationSource currentNavigationSource = null;

                    var entitySetPathSegment = pathSegment as EntitySetSegment;
                    if (entitySetPathSegment != null)
                    {
                        currentNavigationSource = entitySetPathSegment.EntitySet;
                    }

                    var navigationPathSegment = pathSegment as NavigationPropertySegment;
                    if (navigationPathSegment != null)
                    {
                        currentNavigationSource = navigationPathSegment.NavigationSource;
                    }
                    if (containedFound)
                    {
                        odataPath.Add(pathSegment);
                    }
                    else
                    {
                        if (navigationPathSegment != null &&
                            navigationPathSegment.NavigationProperty.ContainsTarget)
                        {
                            containedFound = true;
                            //The path should have the last non-contained navigation property
                            if (previousNavigationPathIndex != -1)
                            {
                                for (int j = previousNavigationPathIndex; j <= i; j++)
                                {
                                    odataPath.Add(segments[j]);
                                }
                            }
                        }
                    }

                    // If we've found our target navigation in the path that means we've correctly populated the
                    // segments up to the navigation and we can ignore the remaining segments.
                    if (currentNavigationSource != null)
                    {
                        previousNavigationPathIndex = i;
                        if (currentNavigationSource == navigationSource)
                        {
                            segmentFound = true;
                            break;
                        }
                    }
                }
            }

            if (!segmentFound || !containedFound)
            {
                // If the target navigation was not found in the current path that means we lack any context that
                // would suggest a scenario other than directly accessing an entity set, so we must assume that's
                // the case.
                odataPath.Clear();

                IEdmContainedEntitySet containmnent = navigationSource as IEdmContainedEntitySet;
                if (containmnent != null)
                {
                    EdmEntityContainer container = new EdmEntityContainer("NS", "Default");
                    IEdmEntitySet      entitySet = new EdmEntitySet(container, navigationSource.Name,
                                                                    navigationSource.EntityType());
                    odataPath.Add(new EntitySetSegment(entitySet));
                }
                else
                {
                    odataPath.Add(new EntitySetSegment((IEdmEntitySet)navigationSource));
                }
            }
        }
예제 #13
0
        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;
        }