Beispiel #1
0
        /// <summary>
        /// Build a test model shared across several tests.
        /// </summary>
        /// <returns>Returns the test model.</returns>
        internal static EntityModelSchema BuildTestModel()
        {
            // The metadata model
            EntityModelSchema model = new EntityModelSchema();

            ComplexType addressType = model.ComplexType("Address")
                .Property("Street", EdmDataTypes.String())
                .Property("Zip", EdmDataTypes.Int32);

            EntityType officeType = model.EntityType("OfficeType")
                .KeyProperty("Id", EdmDataTypes.Int32)
                .Property("Address", DataTypes.ComplexType.WithDefinition(addressType));

            EntityType cityType = model.EntityType("CityType")
                .KeyProperty("Id", EdmDataTypes.Int32)
                .Property("Name", EdmDataTypes.String())
                .NavigationProperty("CityHall", officeType)
                .NavigationProperty("DOL", officeType)
                .NavigationProperty("PoliceStation", officeType, true)
                .NamedStream("Skyline")
                .Property("MetroLanes", DataTypes.CollectionType.WithElementDataType(EdmDataTypes.String()));

            EntityType cityWithMapType = model.EntityType("CityWithMapType")
                .WithBaseType(cityType)
                .DefaultStream();

            EntityType cityOpenType = model.EntityType("CityOpenType")
                .WithBaseType(cityType)
                .OpenType();

            EntityType personType = model.EntityType("Person")
                .KeyProperty("Id", EdmDataTypes.Int32);
            personType = personType.NavigationProperty("Friend", personType);

            EntityType employeeType = model.EntityType("Employee")
                .WithBaseType(personType)
                .Property("CompanyName", EdmDataTypes.String());

            EntityType managerType = model.EntityType("Manager")
                .WithBaseType(employeeType)
                .Property("Level", EdmDataTypes.Int32);

            model.Fixup();

            // Fixed up models will have entity sets for all base entity types.
            model.EntitySet("Employee", employeeType);
            model.EntitySet("Manager", managerType);

            return model;
        }
Beispiel #2
0
        /// <summary>
        /// Creates metadata properties for the specified enumeration of OData OM properties.
        /// </summary>
        /// <param name="model">The model to use.</param>
        /// <param name="owningType">The owning type to which to add the properties.</param>
        /// <param name="properties">Enumeration of the properties to add.</param>
        private static void CreateMetadataProperties(EntityModelSchema model, NamedStructuralType owningType, IEnumerable<ODataProperty> properties)
        {
            if (properties == null)
            {
                return;
            }

            foreach (ODataProperty property in properties)
            {
                ODataPropertyMetadataAnnotation propertyMetadataAnnotation = property.GetInheritedAnnotation<ODataPropertyMetadataAnnotation>();

                object propertyValue = property.Value;
                bool isOpenProperty = false;
                if (propertyMetadataAnnotation != null)
                {
                    isOpenProperty = propertyMetadataAnnotation.IsOpenProperty;
                    ExceptionUtilities.Assert(
                        !isOpenProperty || owningType is EntityType,
                        "Can't declare an open property on non-entity type.");
                    if (propertyMetadataAnnotation.PropertyValueForTypeInference != null)
                    {
                        propertyValue = propertyMetadataAnnotation.PropertyValueForTypeInference;
                    }
                }

                ODataComplexValue complexValue = propertyValue as ODataComplexValue;
                if (complexValue != null)
                {
                    ExceptionUtilities.Assert(complexValue.TypeName.StartsWith(owningType.NamespaceName + "."), "The type name must start with the same namespace as its owning type.");

                    ComplexType complexType = model.GetComplexType(complexValue.TypeName);
                    if (complexType == null)
                    {
                        string complexTypeLocalName = complexValue.TypeName.Substring(owningType.NamespaceName.Length + 1);
                        complexType = model.ComplexType(complexTypeLocalName, owningType.NamespaceName);
                        CreateMetadataProperties(model, complexType, complexValue.Properties);
                    }

                    if (isOpenProperty)
                    {
                        owningType.IsOpen = true;
                    }
                    else
                    {
                        owningType.Property(property.Name, DataTypes.ComplexType.WithDefinition(complexType).Nullable());
                    }
                }
                else
                {
                    bool isKeyProperty = false;
                    bool isETagProperty = false;
                    if (propertyMetadataAnnotation != null)
                    {
                        isKeyProperty = (propertyMetadataAnnotation.Kind & ODataPropertyKind.Key) == ODataPropertyKind.Key;
                        isETagProperty = (propertyMetadataAnnotation.Kind & ODataPropertyKind.ETag) == ODataPropertyKind.ETag;

                        ExceptionUtilities.Assert(
                            !isKeyProperty || owningType is EntityType,
                            "Can't declare a key property on non-entity type.");
                        ExceptionUtilities.Assert(
                            !isETagProperty || owningType is EntityType,
                            "Can't declare an etag property on non-entity type.");
                        ExceptionUtilities.Assert(
                            !isOpenProperty || !(isKeyProperty || isETagProperty),
                            "Key or etag property can't be open.");
                    }

                    if (owningType is EntityType && isOpenProperty)
                    {
                        owningType.IsOpen = true;
                    }
                    else
                    {
                        EntityType owningEntityType = owningType as EntityType;
                        if (owningEntityType != null && isKeyProperty)
                        {
                            ExceptionUtilities.Assert(
                                propertyValue != null,
                                "Found a key property with null value, can't infer type from value in that case and it's invalid anyway.");
                            PrimitiveDataType keyPropertyType = EntityModelUtils.GetPrimitiveEdmType(propertyValue.GetType());
                            owningEntityType.KeyProperty(property.Name, keyPropertyType, isETagProperty);
                        }
                        else
                        {
                            if (propertyValue is ODataCollectionValue)
                            {
                                string itemTypeName = EntityModelUtils.GetCollectionItemTypeName(((ODataCollectionValue)propertyValue).TypeName);
                                CollectionDataType collectionType = null;
                                DataType primitiveItemType = EntityModelUtils.GetPrimitiveEdmType(itemTypeName);
                                if (primitiveItemType != null)
                                {
                                    collectionType = DataTypes.CollectionType.WithElementDataType(primitiveItemType);
                                }
                                else
                                {
                                    ComplexType complexItemType = model.GetComplexType(itemTypeName);
                                    collectionType = DataTypes.CollectionOfComplex(complexItemType);
                                }

                                ExceptionUtilities.Assert(collectionType != null, "Could not resolve item type.");
                                owningType.Property(property.Name, collectionType);
                            }
                            else
                            {
                                Type propertyType = propertyValue == null
                                    ? typeof(string)
                                    : propertyValue.GetType();
                                PrimitiveDataType edmPropertyType = EntityModelUtils.GetPrimitiveEdmType(propertyType);

                                owningType.Property(property.Name, edmPropertyType, isETagProperty);
                            }
                        }
                    }
                }
            }
        }
Beispiel #3
0
        /// <summary>
        /// Creates a test model to test our conversion of OData instances into EDM values.
        /// </summary>
        /// <returns>Returns a model suitable for testing EDM values over OData instances.</returns>
        public static EntityModelSchema BuildEdmValueModel()
        {
            EntityModelSchema model = new EntityModelSchema();
            var complexType = model.ComplexType("ComplexType");
            complexType.Property("IntProp", EdmDataTypes.Int32);
            complexType.Property("StringProp", EdmDataTypes.String());
            complexType.Property("ComplexProp", complexType);

            #region Entity types
            model.EntityContainer("TestContainer");

            // Entity type with a single primitive property
            var singlePrimitivePropertyEntityType = model.EntityType("SinglePrimitivePropertyEntityType");
            singlePrimitivePropertyEntityType.KeyProperty("ID", EdmDataTypes.Int32);
            singlePrimitivePropertyEntityType.Property("Int32Prop", EdmDataTypes.Int32.Nullable());
            model.EntitySet("SinglePrimitivePropertyEntityType", singlePrimitivePropertyEntityType);

            // Entity type with all primitive properties
            var allPrimitivePropertiesEntityType = model.EntityType("AllPrimitivePropertiesEntityType");
            allPrimitivePropertiesEntityType.KeyProperty("ID", EdmDataTypes.Int32);
            allPrimitivePropertiesEntityType.Property("BoolProp", EdmDataTypes.Boolean);
            allPrimitivePropertiesEntityType.Property("Int16Prop", EdmDataTypes.Int16);
            allPrimitivePropertiesEntityType.Property("Int32Prop", EdmDataTypes.Int32);
            allPrimitivePropertiesEntityType.Property("Int64Prop", EdmDataTypes.Int64);
            allPrimitivePropertiesEntityType.Property("ByteProp", EdmDataTypes.Byte);
            allPrimitivePropertiesEntityType.Property("SByteProp", EdmDataTypes.SByte);
            allPrimitivePropertiesEntityType.Property("SingleProp", EdmDataTypes.Single);
            allPrimitivePropertiesEntityType.Property("DoubleProp", EdmDataTypes.Double);
            allPrimitivePropertiesEntityType.Property("DecimalProp", EdmDataTypes.Decimal());
            allPrimitivePropertiesEntityType.Property("DateTimeOffsetProp", EdmDataTypes.DateTimeOffset());
            allPrimitivePropertiesEntityType.Property("DurationProp", EdmDataTypes.Time());
            allPrimitivePropertiesEntityType.Property("GuidProp", EdmDataTypes.Guid);
            allPrimitivePropertiesEntityType.Property("StringProp", EdmDataTypes.String());
            allPrimitivePropertiesEntityType.Property("BinaryProp", EdmDataTypes.Binary());
            model.EntitySet("AllPrimitivePropertiesEntityType", allPrimitivePropertiesEntityType);

            // Entity type with a single complex property
            var singleComplexPropertyEntityType = model.EntityType("SingleComplexPropertyEntityType");
            singleComplexPropertyEntityType.KeyProperty("ID", EdmDataTypes.Int32);
            singleComplexPropertyEntityType.Property("ComplexProp", complexType);
            model.EntitySet("SingleComplexPropertyEntityType", singleComplexPropertyEntityType);

            // Entity type with a single primitive collection property
            var singlePrimitiveCollectionPropertyEntityType = model.EntityType("SinglePrimitiveCollectionPropertyEntityType");
            singlePrimitiveCollectionPropertyEntityType.KeyProperty("ID", EdmDataTypes.Int32);
            singlePrimitiveCollectionPropertyEntityType.Property("PrimitiveCollectionProp", DataTypes.CollectionType.WithElementDataType(EdmDataTypes.Int32));
            model.EntitySet("SinglePrimitiveCollectionPropertyEntityType", singlePrimitiveCollectionPropertyEntityType);

            // Entity type with a single primitive collection property
            var singleComplexCollectionPropertyEntityType = model.EntityType("SingleComplexCollectionPropertyEntityType");
            singleComplexCollectionPropertyEntityType.KeyProperty("ID", EdmDataTypes.Int32);
            singleComplexCollectionPropertyEntityType.Property("ComplexCollectionProp", DataTypes.CollectionOfComplex(complexType));
            model.EntitySet("SingleComplexCollectionPropertyEntityType", singleComplexCollectionPropertyEntityType);

            // Entity type with different property kinds
            var differentPropertyKindsEntityType = model.EntityType("DifferentPropertyKindsEntityType");
            differentPropertyKindsEntityType.KeyProperty("ID", EdmDataTypes.Int32);
            differentPropertyKindsEntityType.Property("ComplexProp", complexType);
            differentPropertyKindsEntityType.Property("PrimitiveCollectionProp", DataTypes.CollectionType.WithElementDataType(EdmDataTypes.Int32));
            differentPropertyKindsEntityType.Property("Int32Prop", EdmDataTypes.Int32);
            differentPropertyKindsEntityType.Property("ComplexCollectionProp", DataTypes.CollectionOfComplex(complexType));
            model.EntitySet("DifferentPropertyKindsEntityType", differentPropertyKindsEntityType);
            #endregion Entity types

            #region Complex types
            // Empty complex type
            var emptyComplexType = model.ComplexType("EmptyComplexType");

            // Complex type with a single primitive property
            var singlePrimitivePropertyComplexType = model.ComplexType("SinglePrimitivePropertyComplexType");
            singlePrimitivePropertyComplexType.Property("Int32Prop", EdmDataTypes.Int32.Nullable());

            // Complex type with all primitive properties
            var allPrimitivePropertiesComplexType = model.ComplexType("AllPrimitivePropertiesComplexType");
            allPrimitivePropertiesComplexType.Property("BoolProp", EdmDataTypes.Boolean);
            allPrimitivePropertiesComplexType.Property("Int16Prop", EdmDataTypes.Int16);
            allPrimitivePropertiesComplexType.Property("Int32Prop", EdmDataTypes.Int32);
            allPrimitivePropertiesComplexType.Property("Int64Prop", EdmDataTypes.Int64);
            allPrimitivePropertiesComplexType.Property("ByteProp", EdmDataTypes.Byte);
            allPrimitivePropertiesComplexType.Property("SByteProp", EdmDataTypes.SByte);
            allPrimitivePropertiesComplexType.Property("SingleProp", EdmDataTypes.Single);
            allPrimitivePropertiesComplexType.Property("DoubleProp", EdmDataTypes.Double);
            allPrimitivePropertiesComplexType.Property("DecimalProp", EdmDataTypes.Decimal());
            allPrimitivePropertiesComplexType.Property("DateTimeOffsetProp", EdmDataTypes.DateTimeOffset());
            allPrimitivePropertiesComplexType.Property("DurationProp", EdmDataTypes.Time());
            allPrimitivePropertiesComplexType.Property("GuidProp", EdmDataTypes.Guid);
            allPrimitivePropertiesComplexType.Property("StringProp", EdmDataTypes.String());
            allPrimitivePropertiesComplexType.Property("BinaryProp", EdmDataTypes.Binary());

            // Complex type with a single complex property
            var singleComplexPropertyComplexType = model.ComplexType("SingleComplexPropertyComplexType");
            singleComplexPropertyComplexType.Property("ComplexProp", complexType);

            // Complex type with a single primitive collection property
            var singlePrimitiveCollectionPropertyComplexType = model.ComplexType("SinglePrimitiveCollectionPropertyComplexType");
            singlePrimitiveCollectionPropertyComplexType.Property("PrimitiveCollectionProp", DataTypes.CollectionType.WithElementDataType(EdmDataTypes.Int32));

            // Complex type with a single primitive collection property
            var singleComplexCollectionPropertyComplexType = model.ComplexType("SingleComplexCollectionPropertyComplexType");
            singleComplexCollectionPropertyComplexType.Property("ComplexCollectionProp", DataTypes.CollectionOfComplex(complexType));

            // Complex type with different property kinds
            var differentPropertyKindsComplexType = model.ComplexType("DifferentPropertyKindsComplexType");
            differentPropertyKindsComplexType.Property("ComplexProp", complexType);
            differentPropertyKindsComplexType.Property("PrimitiveCollectionProp", DataTypes.CollectionType.WithElementDataType(EdmDataTypes.Int32));
            differentPropertyKindsComplexType.Property("Int32Prop", EdmDataTypes.Int32);
            differentPropertyKindsComplexType.Property("ComplexCollectionProp", DataTypes.CollectionOfComplex(complexType));
            #endregion Complex types

            return model.Fixup();
        }
Beispiel #4
0
        /// <summary>
        /// Build a test model shared across several tests.
        /// </summary>
        /// <returns>Returns the test model.</returns>
        public static EntityModelSchema BuildTestModel()
        {
            // The metadata model
            EntityModelSchema model = new EntityModelSchema().MinimumVersion(ODataVersion.V4);

            ComplexType addressType = model.ComplexType("Address")
                .Property("Street", EdmDataTypes.String().Nullable())
                .Property("Zip", EdmDataTypes.Int32);

            EntityType officeType = model.EntityType("OfficeType")
                .KeyProperty("Id", EdmDataTypes.Int32)
                .Property("Address", DataTypes.ComplexType.WithDefinition(addressType));

            EntityType officeWithNumberType = model.EntityType("OfficeWithNumberType")
                .WithBaseType(officeType)
                .Property("Number", EdmDataTypes.Int32);

            EntityType cityType = model.EntityType("CityType")
                .KeyProperty("Id", EdmDataTypes.Int32)
                .Property("Name", EdmDataTypes.String().Nullable())
                .NavigationProperty("CityHall", officeType)
                .NavigationProperty("DOL", officeType)
                .NavigationProperty("PoliceStation", officeType, true)
                .StreamProperty("Skyline")
                .Property("MetroLanes", DataTypes.CollectionType.WithElementDataType(EdmDataTypes.String().Nullable()));

            EntityType cityWithMapType = model.EntityType("CityWithMapType")
                .WithBaseType(cityType)
                .DefaultStream();

            EntityType cityOpenType = model.EntityType("CityOpenType")
                .WithBaseType(cityType)
                .OpenType();

            EntityType personType = model.EntityType("Person")
                .KeyProperty("Id", EdmDataTypes.Int32);
            personType = personType.NavigationProperty("Friend", personType);

            EntityType employeeType = model.EntityType("Employee")
                .WithBaseType(personType)
                .Property("CompanyName", EdmDataTypes.String().Nullable());

            EntityType managerType = model.EntityType("Manager")
                .WithBaseType(employeeType)
                .Property("Level", EdmDataTypes.Int32);

            model.Add(new EntityContainer("DefaultContainer"));

            model.EntitySet("Offices", officeType);
            model.EntitySet("Cities", cityType);
            model.EntitySet("Persons", personType);

            model.Fixup();

            // Fixed up models will have entity sets for all base entity types.
            model.EntitySet("Employee", employeeType);
            model.EntitySet("Manager", managerType);

            EntityContainer container = model.EntityContainers.Single();

            // NOTE: Function import parameters and return types must be nullable as per current CSDL spec
            FunctionImport serviceOp = container.FunctionImport("ServiceOperation1")
                .Parameter("a", EdmDataTypes.Int32.Nullable())
                .Parameter("b", EdmDataTypes.String().Nullable())
                .ReturnType(EdmDataTypes.Int32.Nullable());

            container.FunctionImport("PrimitiveResultOperation")
                .ReturnType(EdmDataTypes.Int32.Nullable());
            container.FunctionImport("ComplexResultOperation")
                .ReturnType(DataTypes.ComplexType.WithDefinition(addressType).Nullable());
            container.FunctionImport("PrimitiveCollectionResultOperation")
                .ReturnType(DataTypes.CollectionType.WithElementDataType(EdmDataTypes.Int32.Nullable()));
            container.FunctionImport("ComplexCollectionResultOperation")
                .ReturnType(DataTypes.CollectionType.WithElementDataType(DataTypes.ComplexType.WithDefinition(addressType).Nullable()));

            // Overload with 0 Param
            container.FunctionImport("FunctionImportWithOverload");

            // Overload with 1 Param
            container.FunctionImport("FunctionImportWithOverload")
                .Parameter("p1", DataTypes.EntityType.WithDefinition(cityWithMapType));

            // Overload with 2 Params
            container.FunctionImport("FunctionImportWithOverload")
                .Parameter("p1", DataTypes.EntityType.WithDefinition(cityType))
                .Parameter("p2", EdmDataTypes.String().Nullable());

            // Overload with 5 Params
            container.FunctionImport("FunctionImportWithOverload")
                .Parameter("p1", DataTypes.CollectionOfEntities(cityType))
                .Parameter("p2", DataTypes.CollectionType.WithElementDataType(EdmDataTypes.String().Nullable()))
                .Parameter("p3", EdmDataTypes.String().Nullable())
                .Parameter("p4", DataTypes.ComplexType.WithDefinition(addressType).Nullable())
                .Parameter("p5", DataTypes.CollectionType.WithElementDataType(DataTypes.ComplexType.WithDefinition(addressType).Nullable()));

            return model;
        }
Beispiel #5
0
        /// <summary>
        /// Creates a set of models.
        /// </summary>
        /// <returns>List of interesting entity reference link instances.</returns>
        public static IEnumerable<EntityModelSchema> CreateModels()
        {
            //
            // NOTE: we only create a few models here since we mostly rely on EdmLib to test 
            //       model serialization/deserialization for us
            //
            // Empty model
            EntityModelSchema emptyModel = new EntityModelSchema().MinimumVersion(ODataVersion.V4);
            emptyModel.Fixup();
            yield return emptyModel;

            // Model with a single entity type
            EntityModelSchema modelWithSingleEntityType = new EntityModelSchema().MinimumVersion(ODataVersion.V4);
            modelWithSingleEntityType.EntityType("SingletonEntityType")
                .KeyProperty("Id", EdmDataTypes.Int32)
                .Property("Name", EdmDataTypes.String().Nullable());
            modelWithSingleEntityType.Fixup();
            yield return modelWithSingleEntityType;

            // Model with a single complex type
            EntityModelSchema modelWithSingleComplexType = new EntityModelSchema().MinimumVersion(ODataVersion.V4);
            modelWithSingleComplexType.ComplexType("SingletonComplexType")
                .Property("City", EdmDataTypes.String().Nullable());
            modelWithSingleComplexType.Fixup();
            yield return modelWithSingleComplexType;

            // Model with a collection property
            EntityModelSchema modelWithCollectionProperty = new EntityModelSchema().MinimumVersion(ODataVersion.V4);
            modelWithCollectionProperty.ComplexType("EntityTypeWithCollection")
                .Property("Cities", DataTypes.CollectionType.WithElementDataType(EdmDataTypes.String().Nullable()));
            modelWithCollectionProperty.Fixup();
            yield return modelWithCollectionProperty;

            // Model with an open type
            EntityModelSchema modelWithOpenType = new EntityModelSchema().MinimumVersion(ODataVersion.V4);
            EntityType openType = modelWithOpenType.EntityType("OpenEntityType").KeyProperty("Id", EdmDataTypes.Int32);
            openType.IsOpen = true;
            modelWithOpenType.Fixup();
            yield return modelWithOpenType;

            // Model with a named stream
            EntityModelSchema modelWithNamedStream = new EntityModelSchema().MinimumVersion(ODataVersion.V4);
            modelWithNamedStream.EntityType("NamedStreamEntityType")
                .KeyProperty("Id", EdmDataTypes.Int32)
                .StreamProperty("NamedStream");
            modelWithNamedStream.Fixup();
            yield return modelWithNamedStream;

            // OData Shared Test Model
            yield return BuildTestModel();

            // Model with OData-specific attribute annotations
            yield return BuildODataAnnotationTestModel(true);

            // Astoria Default Test Model
            yield return BuildDefaultAstoriaTestModel();
        }
Beispiel #6
0
        /// <summary>
        /// Build a test model shared across several tests.
        /// </summary>
        /// <param name="addAnnotations">true if the annotations should be added upon construction; otherwise false.</param>
        /// <returns>Returns the test model.</returns>
        public static EntityModelSchema BuildODataAnnotationTestModel(bool addAnnotations)
        {
            // The metadata model with OData-specific annotations
            // - default entity container annotation
            // - HasStream annotation on entity type
            // - MimeType annotation on primitive property
            // - MimeType annotation on service operation
            EntityModelSchema model = new EntityModelSchema().MinimumVersion(ODataVersion.V4);

            ComplexType addressType = model.ComplexType("Address")
                .Property("Street", EdmDataTypes.String().Nullable())
                .Property("Zip", EdmDataTypes.Int32);
            if (addAnnotations)
            {
                addressType.Properties.Where(p => p.Name == "Zip").Single().MimeType("text/plain");
            }

            EntityType personType = model.EntityType("PersonType")
                .KeyProperty("Id", EdmDataTypes.Int32)
                .Property("Name", EdmDataTypes.String())
                .Property("Address", DataTypes.ComplexType.WithDefinition(addressType))
                .StreamProperty("Picture")
                .DefaultStream();
            if (addAnnotations)
            {
                personType.Properties.Where(p => p.Name == "Name").Single().MimeType("text/plain");
            }

            model.Fixup();

            // set the default container
            EntityContainer container = model.EntityContainers.Single();

            model.EntitySet("People", personType);

            // NOTE: Function import parameters and return types must be nullable as per current CSDL spec
            FunctionImport serviceOp = container.FunctionImport("ServiceOperation1")
                .Parameter("a", EdmDataTypes.Int32.Nullable())
                .Parameter("b", EdmDataTypes.String().Nullable())
                .ReturnType(EdmDataTypes.Int32.Nullable());
            if (addAnnotations)
            {
                serviceOp.MimeType("img/jpeg");
            }

            return model;
        }