public void EntityKeyConvention_DoesnotFigureOutKeyPropertyOnDerivedTypes() { MockType baseType = new MockType("BaseType") .Property <uint>("ID"); MockType derivedType = new MockType("DerivedType") .Property <int>("DerivedTypeID") .BaseType(baseType); ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); builder.AddEntity(derivedType).DerivesFrom(builder.AddEntity(baseType)); IEdmModel model = builder.GetEdmModel(); IEdmEntityType baseEntity = model.AssertHasEntityType(baseType); baseEntity.AssertHasKey(model, "ID", EdmPrimitiveTypeKind.Int64); IEdmEntityType derivedEntity = model.AssertHasEntityType(derivedType); derivedEntity.AssertHasPrimitiveProperty(model, "DerivedTypeID", EdmPrimitiveTypeKind.Int32, isNullable: false); }
public void RemoveBaseTypeProperties_RemovesAllBaseTypePropertiesFromDerivedTypes() { var mockType1 = new MockType("Foo").Property <int>("P1"); var mockType2 = new MockType("Bar").BaseType(mockType1).Property <int>("P1").Property <int>("P2"); var mockType3 = new MockType("FooBar").BaseType(mockType2).Property <int>("P1").Property <int>("P2"); var mockAssembly = new MockAssembly(mockType1, mockType2, mockType3); HttpConfiguration configuration = new HttpConfiguration(); configuration.Services.Replace(typeof(IAssembliesResolver), new TestAssemblyResolver(mockAssembly)); var builder = new ODataConventionModelBuilder(configuration); var entity1 = builder.AddEntity(mockType1); entity1.AddProperty(mockType1.GetProperty("P1")); var entity2 = builder.AddEntity(mockType2).DerivesFrom(entity1); entity2.AddProperty(mockType2.GetProperty("P2")); var entity3 = builder.AddEntity(mockType3); entity3.AddProperty(mockType3.GetProperty("P1")); entity3.AddProperty(mockType3.GetProperty("P2")); builder.RemoveBaseTypeProperties(entity3, entity2); Assert.Empty(entity3.Properties); }
public static IEdmModel GetEdmModel() { var builder = new ODataConventionModelBuilder(); builder.EntitySet <Product>("Product"); builder.AddEntity(typeof(Details)); builder.AddEntity(typeof(Language)); return(builder.GetEdmModel()); }
public void ModelBuilder_DeepChainOfComplexTypes() { var modelBuilder = new ODataConventionModelBuilder(); MockType entityType = new MockType("SampleType") .Property <int>("ID") .Property( new MockType("ComplexType1") .Property( new MockType("ComplexType2") .Property( new MockType("ComplexType3") .Property <int>("Property"), "Property"), "Property"), "Property"); modelBuilder.AddEntity(entityType); var model = modelBuilder.GetEdmModel(); Assert.NotNull(model.FindType("DefaultNamespace.SampleType") as IEdmEntityType); Assert.NotNull(model.FindType("DefaultNamespace.ComplexType1") as IEdmComplexType); Assert.NotNull(model.FindType("DefaultNamespace.ComplexType2") as IEdmComplexType); Assert.NotNull(model.FindType("DefaultNamespace.ComplexType3") as IEdmComplexType); }
public void EntityType_Containing_ComplexTypeContainingComplexCollection_Works() { Type complexTypeWithComplexCollection = new MockType("ComplexType") .Property <Version[]>("ComplexCollectionProperty"); Type entityType = new MockType("EntityTypeWithComplexCollection") .Property <int>("ID") .Property(complexTypeWithComplexCollection, "ComplexProperty"); var modelBuilder = new ODataConventionModelBuilder(); modelBuilder.AddEntity(entityType); var model = modelBuilder.GetEdmModel(); IEdmEntityType entityEdmType = model.AssertHasEntityType(entityType); model.AssertHasComplexType(typeof(Version)); IEdmComplexType edmComplexType = model.AssertHasComplexType(complexTypeWithComplexCollection); var collectionProperty = edmComplexType.DeclaredProperties.Where(p => p.Name == "ComplexCollectionProperty").SingleOrDefault(); Assert.NotNull(collectionProperty); Assert.True(collectionProperty.Type.IsCollection()); Assert.Equal(collectionProperty.Type.AsCollection().ElementType().FullName(), "System.Version"); }
public void ModelBuilder_SupportsComplexCollectionWhenNotToldElementTypeIsComplex(Type complexCollectionPropertyType) { var modelBuilder = new ODataConventionModelBuilder(); Type entityType = CreateDynamicType( new DynamicType { TypeName = "SampleType", Properties = { new DynamicProperty { Name = "ID", Type = typeof(int) }, new DynamicProperty { Name = "Property1", Type = complexCollectionPropertyType } } }); modelBuilder.AddEntity(entityType); IEdmModel model = modelBuilder.GetEdmModel(); IEdmEntityType entity = model.GetEdmType(entityType) as IEdmEntityType; Assert.NotNull(entity); Assert.Equal(2, entity.DeclaredProperties.Count()); IEdmStructuralProperty property1 = entity.DeclaredProperties.OfType <IEdmStructuralProperty>().SingleOrDefault(p => p.Name == "Property1"); Assert.NotNull(property1); Assert.Equal(EdmTypeKind.Collection, property1.Type.Definition.TypeKind); Assert.Equal(EdmTypeKind.Complex, (property1.Type.Definition as IEdmCollectionType).ElementType.Definition.TypeKind); }
/// <summary> /// Get the OData metadata about the reliable collections from the reliable state manager using reflection. /// </summary> /// <param name="stateManager">Reliable state manager for the replica.</param> /// <returns>The OData metadata for this state manager.</returns> public static async Task <string> GetMetadataAsync(this IReliableStateManager stateManager) { // Build the OData model from the queryable types in the reliable state manager. var builder = new ODataConventionModelBuilder(); foreach (var queryable in await stateManager.GetQueryableTypes().ConfigureAwait(false)) { var qkey = queryable.Key; var qkey2 = qkey.Replace('.', '#'); Console.WriteLine(qkey2); dictEntityMap.Add(queryable.Key, qkey2); var entity = builder.AddEntity(queryable.Value); builder.AddEntitySet(qkey2, entity); } var model = builder.GetEdmModel(); // Write the OData metadata document. using (var stream = new MemoryStream()) using (var message = new InMemoryMessage { Stream = stream }) { var settings = new ODataMessageWriterSettings(); var writer = new ODataMessageWriter((IODataResponseMessage)message, settings, model); writer.WriteMetadataDocument(); return(Encoding.UTF8.GetString(stream.ToArray())); } }
public void Apply_Doesnot_Override_UserConfiguration() { ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); var vehicles = builder.EntitySet<Vehicle>("vehicles"); var car = builder.AddEntity(typeof(Car)); var paintAction = vehicles.EntityType.Action("Paint"); paintAction.HasActionLink(ctxt => new Uri("http://localhost/ActionTestWorks"), followsConventions: false); ActionLinkGenerationConvention convention = new ActionLinkGenerationConvention(); convention.Apply(paintAction, builder); IEdmModel model = builder.GetEdmModel(); var vehiclesEdmSet = model.EntityContainers().Single().FindEntitySet("vehicles"); var carEdmType = model.FindDeclaredType("System.Web.Http.OData.Builder.TestModels.Car") as IEdmEntityType; var paintEdmAction = model.GetAvailableProcedures( model.FindDeclaredType("System.Web.Http.OData.Builder.TestModels.Car") as IEdmEntityType).Single() as IEdmAction; Assert.NotNull(paintEdmAction); HttpConfiguration configuration = new HttpConfiguration(); configuration.Routes.MapODataRoute(model); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost"); request.SetConfiguration(configuration); ActionLinkBuilder actionLinkBuilder = model.GetActionLinkBuilder(paintEdmAction); var serializerContext = new ODataSerializerContext { Model = model, EntitySet = vehiclesEdmSet, Url = request.GetUrlHelper() }; var entityContext = new EntityInstanceContext(serializerContext, carEdmType.AsReference(), new Car { Model = 2009, Name = "Accord" }); Uri link = actionLinkBuilder.BuildActionLink(entityContext); Assert.Equal("http://localhost/ActionTestWorks", link.AbsoluteUri); }
public void ModelBuilder_DerivedComplexTypeHavingKeys_Throws() { MockType baseComplexType = new MockType("BaseComplexType"); MockType derivedComplexType = new MockType("DerivedComplexType") .Property(typeof(int), "DerivedComplexTypeId") .BaseType(baseComplexType); MockType entityType = new MockType("EntityType") .Property(typeof(int), "ID") .Property(baseComplexType.Object, "ComplexProperty"); MockAssembly assembly = new MockAssembly(baseComplexType, derivedComplexType, entityType); HttpConfiguration configuration = new HttpConfiguration(); configuration.Services.Replace(typeof(IAssembliesResolver), new TestAssemblyResolver(assembly)); var builder = new ODataConventionModelBuilder(configuration); builder.AddEntitySet("entities", builder.AddEntity(entityType)); Assert.Throws <InvalidOperationException>( () => builder.GetEdmModel(), "Cannot define keys on type 'DefaultNamespace.DerivedComplexType' deriving from 'DefaultNamespace.BaseComplexType'. Only the root type in the entity inheritance hierarchy can contain keys."); }
public void GenerateSelfLinkWithCast_Works() { ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); var vehicles = builder.AddEntitySet("cars", builder.AddEntity(typeof(Car))); IEdmModel model = builder.GetEdmModel(); IEdmEntitySet carsEdmEntitySet = model.EntityContainers().Single().EntitySets().Single(); HttpConfiguration configuration = new HttpConfiguration(); string routeName = "Route"; configuration.Routes.MapODataRoute(routeName, null, model); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost"); request.SetConfiguration(configuration); request.SetODataRouteName(routeName); string idLink = SelfLinksGenerationConvention.GenerateSelfLink( vehicles, new EntityInstanceContext() { EdmModel = model, EntitySet = carsEdmEntitySet, EntityType = carsEdmEntitySet.ElementType, Url = request.GetUrlHelper(), EntityInstance = new Car { Model = 2009, Name = "Accord" } }, includeCast: true); Assert.Equal("http://localhost/cars(Model=2009,Name='Accord')/System.Web.Http.OData.Builder.TestModels.Car", idLink); }
public void GenerateNavigationLink_GeneratesLink() { ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); var orders = builder.AddEntitySet("Orders", builder.AddEntity(typeof(NavigationLinksGenerationConventionTest_Order))); IEdmModel model = builder.GetEdmModel(); var edmEntitySet = model.EntityContainers().Single().EntitySets().Single(); HttpConfiguration configuration = new HttpConfiguration(); configuration.EnableOData(model); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost"); request.Properties[HttpPropertyKeys.HttpConfigurationKey] = configuration; request.Properties[HttpPropertyKeys.HttpRouteDataKey] = new HttpRouteData(new HttpRoute()); Uri uri = NavigationLinksGenerationConvention.GenerateNavigationPropertyLink( new EntityInstanceContext { EdmModel = model, EntityInstance = new NavigationLinksGenerationConventionTest_Order { ID = 100 }, EntitySet = edmEntitySet, EntityType = edmEntitySet.ElementType, UrlHelper = request.GetUrlHelper(), PathHandler = new DefaultODataPathHandler(model) }, edmEntitySet.ElementType.NavigationProperties().Single(), orders, includeCast: false); Assert.Equal("http://localhost/Orders(100)/Customer", uri.AbsoluteUri); }
public void GenerateSelfLinkWithoutCast_Works() { ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); var vehicles = builder.AddEntitySet("cars", builder.AddEntity(typeof(Car))); IEdmModel model = builder.GetEdmModel(); IEdmEntitySet carsEdmEntitySet = model.EntityContainers().Single().EntitySets().Single(); HttpConfiguration configuration = new HttpConfiguration(); configuration.Routes.MapHttpRoute(ODataRouteNames.GetById, "{controller}({id})"); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost"); request.Properties[HttpPropertyKeys.HttpConfigurationKey] = configuration; request.Properties[HttpPropertyKeys.HttpRouteDataKey] = new HttpRouteData(new HttpRoute()); Uri uri = SelfLinksGenerationConvention.GenerateSelfLink( vehicles, new EntityInstanceContext(model, carsEdmEntitySet, carsEdmEntitySet.ElementType, request.GetUrlHelper(), new Car { Model = 2009, Name = "Accord" }), includeCast: false); Assert.Equal("http://localhost/cars(Model=2009,Name='Accord')", uri.AbsoluteUri); }
public void DatabaseGeneratedAttributeEdmPropertyConvention_DoesnotOverwriteExistingConfiguration() { // Arrange MockType type = new MockType("Entity") .Property(typeof(int), "ID") .Property(typeof(int?), "Count", new DatabaseGeneratedAttribute(DatabaseGeneratedOption.Computed)); // Act ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); builder.AddEntity(type).AddProperty(type.GetProperty("Count")).IsOptional(); IEdmModel model = builder.GetEdmModel(); // Assert IEdmEntityType entity = model.AssertHasEntityType(type); IEdmStructuralProperty property = entity.AssertHasPrimitiveProperty(model, "Count", EdmPrimitiveTypeKind.Int32, isNullable: true); var idAnnotation = model.GetAnnotationValue <EdmStringConstant>( property, StoreGeneratedPatternAnnotation.AnnotationsNamespace, "StoreGeneratedPattern"); Assert.Null(idAnnotation); }
public void GenerateNavigationLink_GeneratesCorrectLink_EvenIfRouteDataPointsToADifferentController() { ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); var orders = builder.AddEntitySet("Orders", builder.AddEntity(typeof(NavigationLinksGenerationConventionTest_Order))); IEdmModel model = builder.GetEdmModel(); var edmEntitySet = model.EntityContainers().Single().EntitySets().Single(); HttpConfiguration configuration = new HttpConfiguration(); string routeName = "Route"; configuration.Routes.MapODataRoute(routeName, null, model); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost"); request.SetConfiguration(configuration); request.SetODataRouteName(routeName); Uri uri = NavigationLinksGenerationConvention.GenerateNavigationPropertyLink( new EntityInstanceContext { EdmModel = model, EntityInstance = new NavigationLinksGenerationConventionTest_Order { ID = 100 }, EntitySet = edmEntitySet, EntityType = edmEntitySet.ElementType, Url = request.GetUrlHelper() }, edmEntitySet.ElementType.NavigationProperties().Single(), orders, includeCast: false); Assert.Equal("http://localhost/Orders(100)/Customer", uri.AbsoluteUri); }
//In case you want to typecast or inject into current ODataQueryOptions, //you can use this method to build new one from the odata query string public static ODataQueryOptions <T> BuildOptions(string oDataUri) { var baseUri = ""; var odUri = ""; var spl = oDataUri.Split('?'); if (spl.Count() == 0) { odUri = spl[0]; } else { baseUri = spl[0]; odUri = spl[1]; } if (string.IsNullOrEmpty(baseUri)) { baseUri = "http://localhost/api/" + typeof(T).Name; } var request = new HttpRequestMessage(HttpMethod.Get, baseUri + "?" + oDataUri.Replace("?", "")); var modelBuilder = new ODataConventionModelBuilder(); modelBuilder.AddEntity(typeof(T)); var edmModel = modelBuilder.GetEdmModel(); var oDataQueryContext = new ODataQueryContext(edmModel, typeof(T)); return(new ODataQueryOptions <T>(oDataQueryContext, request)); }
public void CanBuildModelForAnonymousTypes() { Type entityType = new { ID = default(int), ComplexCollection = new[] { new { ComplexProperty = default(string) } }, NavigationCollection = new[] { new { ID = default(int) } } }.GetType(); ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); builder.AddEntitySet("entityset", builder.AddEntity(entityType)); IEdmModel model = builder.GetEdmModel(); IEdmEntityType entity = model.AssertHasEntitySet("entityset", entityType); entity.AssertHasKey(model, "ID", EdmPrimitiveTypeKind.Int32); entity.AssertHasCollectionProperty(model, "ComplexCollection", new { ComplexProperty = default(string) }.GetType(), isNullable: true); entity.AssertHasNavigationProperty(model, "NavigationCollection", new { ID = default(int) }.GetType(), isNullable: false, multiplicity: EdmMultiplicity.ZeroOrOne); IEdmComplexType complexType = model.AssertHasComplexType(new { ComplexProperty = default(string) }.GetType()); complexType.AssertHasPrimitiveProperty(model, "ComplexProperty", EdmPrimitiveTypeKind.String, isNullable: true); }
public void GenerateNavigationLink_GeneratesCorrectLink_EvenIfRouteDataPointsToADifferentController() { ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); var orders = builder.AddEntitySet("Orders", builder.AddEntity(typeof(NavigationLinksGenerationConventionTest_Order))); IEdmModel model = builder.GetEdmModel(); var edmEntitySet = model.EntityContainers().Single().EntitySets().Single(); HttpConfiguration configuration = new HttpConfiguration(); var route = configuration.Routes.MapHttpRoute(ODataRouteNames.PropertyNavigation, "{controller}({parentId})/{navigationProperty}"); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost"); request.Properties[HttpPropertyKeys.HttpConfigurationKey] = configuration; request.Properties[HttpPropertyKeys.HttpRouteDataKey] = new HttpRouteData(route, new HttpRouteValueDictionary(new { controller = "Customers" })); Uri uri = NavigationLinksGenerationConvention.GenerateNavigationPropertyLink( new EntityInstanceContext { EdmModel = model, EntityInstance = new NavigationLinksGenerationConventionTest_Order { ID = 100 }, EntitySet = edmEntitySet, EntityType = edmEntitySet.ElementType, UrlHelper = request.GetUrlHelper() }, edmEntitySet.ElementType.NavigationProperties().Single(), orders, includeCast: false); Assert.Equal("http://localhost/Orders(100)/Customer", uri.AbsoluteUri); }
public void Apply_Doesnot_Override_UserConfiguration() { ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); var vehicles = builder.EntitySet <Vehicle>("vehicles"); var car = builder.AddEntity(typeof(Car)); var paintAction = vehicles.EntityType.Action("Paint"); paintAction.HasActionLink(ctxt => new Uri("http://localhost/ActionTestWorks")); _convention.Apply(paintAction, builder); IEdmModel model = builder.GetEdmModel(); var vehiclesEdmSet = model.EntityContainers().Single().FindEntitySet("vehicles"); var carEdmType = model.FindDeclaredType("System.Web.Http.OData.Builder.TestModels.Car") as IEdmEntityType; var paintEdmAction = model.GetAvailableProcedures(model.FindDeclaredType("System.Web.Http.OData.Builder.TestModels.Car") as IEdmEntityType).Single(); HttpConfiguration configuration = new HttpConfiguration(); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost"); request.Properties[HttpPropertyKeys.HttpConfigurationKey] = configuration; request.Properties[HttpPropertyKeys.HttpRouteDataKey] = new HttpRouteData(new HttpRoute()); ActionLinkBuilder actionLinkBuilder = model.GetActionLinkBuilder(paintEdmAction); Uri link = actionLinkBuilder.BuildActionLink(new EntityInstanceContext(model, vehiclesEdmSet, carEdmType, request.GetUrlHelper(), new Car { Model = 2009, Name = "Accord" })); Assert.Equal( "http://localhost/ActionTestWorks", link.AbsoluteUri); }
public void ModelBuilder_DerivedComplexTypeHavingKeys_SuccedsIfToldToBeComplex() { MockType baseComplexType = new MockType("BaseComplexType"); MockType derivedComplexType = new MockType("DerivedComplexType") .Property(typeof(int), "DerivedComplexTypeId") .BaseType(baseComplexType); MockType entityType = new MockType("EntityType") .Property(typeof(int), "ID") .Property(baseComplexType.Object, "ComplexProperty"); MockAssembly assembly = new MockAssembly(baseComplexType, derivedComplexType, entityType); HttpConfiguration configuration = new HttpConfiguration(); configuration.Services.Replace(typeof(IAssembliesResolver), new TestAssemblyResolver(assembly)); var builder = new ODataConventionModelBuilder(configuration); builder.AddEntitySet("entities", builder.AddEntity(entityType)); builder.AddComplexType(baseComplexType); IEdmModel model = builder.GetEdmModel(); Assert.Equal(3, model.SchemaElements.Count()); Assert.NotNull(model.FindType("DefaultNamespace.EntityType")); Assert.NotNull(model.FindType("DefaultNamespace.BaseComplexType")); }
public void GenerateSelfLinkWithCast_Works() { ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); var vehicles = builder.AddEntitySet("cars", builder.AddEntity(typeof(Car))); IEdmModel model = builder.GetEdmModel(); IEdmEntitySet carsEdmEntitySet = model.EntityContainers().Single().EntitySets().Single(); HttpConfiguration configuration = new HttpConfiguration(); configuration.EnableOData(model); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost"); request.Properties[HttpPropertyKeys.HttpConfigurationKey] = configuration; request.Properties[HttpPropertyKeys.HttpRouteDataKey] = new HttpRouteData(new HttpRoute()); Uri uri = SelfLinksGenerationConvention.GenerateSelfLink( vehicles, new EntityInstanceContext() { EdmModel = model, EntitySet = carsEdmEntitySet, EntityType = carsEdmEntitySet.ElementType, UrlHelper = request.GetUrlHelper(), PathHandler = new DefaultODataPathHandler(model), EntityInstance = new Car { Model = 2009, Name = "Accord" } }, includeCast: true); Assert.Equal("http://localhost/cars(Model=2009,Name='Accord')/System.Web.Http.OData.Builder.TestModels.Car", uri.AbsoluteUri); }
public void DiscoverInheritanceRelationships_PatchesBaseType() { var mockType1 = new MockType("Foo"); var mockType2 = new MockType("Bar").BaseType(mockType1); var mockAssembly = new MockAssembly(mockType1, mockType2); HttpConfiguration configuration = new HttpConfiguration(); configuration.Services.Replace(typeof(IAssembliesResolver), new TestAssemblyResolver(mockAssembly)); var builder = new ODataConventionModelBuilder(configuration); var entity1 = builder.AddEntity(mockType1); var entity2 = builder.AddEntity(mockType2); builder.DiscoverInheritanceRelationships(); Assert.Equal(entity1, entity2.BaseType); }
private static ODataQueryContext CreateQueryContext(Type type) { var builder = new ODataConventionModelBuilder(); builder.AddEntity(type); var model = builder.GetEdmModel(); return(new ODataQueryContext(model, type)); }
public void ModelBuilder_DeepChainOfComplexTypes() { var modelBuilder = new ODataConventionModelBuilder(); Type entityType = CreateDynamicType( new DynamicType { TypeName = "SampleType", Properties = { new DynamicProperty { Name = "ID", Type = typeof(int) }, new DynamicProperty { Name = "Property", Type = new DynamicType { TypeName = "ComplexType1", Properties = { new DynamicProperty { Name = "Property", Type = new DynamicType { TypeName = "ComplexType2", Properties = { new DynamicProperty { Name = "Property", Type = new DynamicType { TypeName = "ComplexType3", Properties ={ new DynamicProperty { Name = "Property", Type = typeof(int) } } } } } } } } } } } }); modelBuilder.AddEntity(entityType); var model = modelBuilder.GetEdmModel(); Assert.NotNull(model.FindType("SampleNamespace.SampleType")); Assert.NotNull(model.FindType("SampleNamespace.ComplexType1")); Assert.NotNull(model.FindType("SampleNamespace.ComplexType2")); Assert.NotNull(model.FindType("SampleNamespace.ComplexType3")); }
private static ODataQueryContext GetQueryContext() { var type = typeof(UserProfile); var builder = new ODataConventionModelBuilder(); builder.AddEntity(type); var model = builder.GetEdmModel(); return(new ODataQueryContext(model, type)); }
public void ModelBuilder_PrunesUnReachableTypes(MockType type) { var modelBuilder = new ODataConventionModelBuilder(); modelBuilder.AddEntity(type); var model = modelBuilder.GetEdmModel(); Assert.True(model.FindType("DefaultNamespace.IgnoredType") == null); }
public void ModelBuilder_AnyType_QueryComposition(Type type) { var modelBuilder = new ODataConventionModelBuilder(isQueryCompositionMode: true); modelBuilder.AddEntity(type); IEdmModel model = modelBuilder.GetEdmModel(); Assert.True(model.SchemaElements.Count() > 0); IEdmEntityType entityType = Assert.IsAssignableFrom <IEdmEntityType>(model.FindType(type.EdmFullName())); }
public void ModelBuilder_PrunesUnReachableTypes(DynamicType type) { var modelBuilder = new ODataConventionModelBuilder(); Type entityType = CreateDynamicType(type); modelBuilder.AddEntity(entityType); var model = modelBuilder.GetEdmModel(); Assert.True(model.FindType("SampleNamespace.IgnoredType") == null); }
public static IEdmModel GetEdmModel(HttpConfiguration configuration) { ODataConventionModelBuilder builder = new ODataConventionModelBuilder(configuration); foreach (var type in Creator.EntityTypes) { var entity = builder.AddEntity(type); builder.AddEntitySet(type.Name, entity); } return(builder.GetEdmModel()); }
internal static IEdmModel GetEdmModel(this HttpActionDescriptor actionDescriptor, Type entityClrType) { // save the EdmModel to the action descriptor return(actionDescriptor.Properties.GetOrAdd(EdmModelKey + entityClrType.FullName, _ => { ODataConventionModelBuilder builder = new ODataConventionModelBuilder(actionDescriptor.Configuration, isQueryCompositionMode: true); EntityTypeConfiguration entityTypeConfiguration = builder.AddEntity(entityClrType); builder.AddEntitySet(entityClrType.Name, entityTypeConfiguration); IEdmModel edmModel = builder.GetEdmModel(); return edmModel; }) as IEdmModel); }
public void ModelBuilder_DoesnotThrow_ForEntityCollection(Type collectionType) { var modelBuilder = new ODataConventionModelBuilder(); Type entityType = new MockType("SampleType") .Property <int>("ID") .Property(collectionType, "Products"); modelBuilder.AddEntity(entityType); Assert.DoesNotThrow( () => modelBuilder.GetEdmModel()); }
public void EntityKeyConvention_DoesnotFigureOutKeyPropertyOnDerivedTypes() { MockType baseType = new MockType("BaseType") .Property<uint>("ID"); MockType derivedType = new MockType("DerivedType") .Property<int>("DerivedTypeID") .BaseType(baseType); ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); builder.AddEntity(derivedType).DerivesFrom(builder.AddEntity(baseType)); IEdmModel model = builder.GetEdmModel(); IEdmEntityType baseEntity = model.AssertHasEntityType(baseType); baseEntity.AssertHasKey(model, "ID", EdmPrimitiveTypeKind.Int64); IEdmEntityType derivedEntity = model.AssertHasEntityType(derivedType); derivedEntity.AssertHasPrimitiveProperty(model, "DerivedTypeID", EdmPrimitiveTypeKind.Int32, isNullable: false); }
public void RequiredAttributeEdmPropertyConvention_ConfiguresRequiredPropertyAsRequired() { MockType type = new MockType("Entity") .Property(typeof(int), "ID") .Property(typeof(int?), "Count", new RequiredAttribute()); ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); builder.AddEntity(type); IEdmModel model = builder.GetEdmModel(); IEdmEntityType entity = model.AssertHasEntityType(type); entity.AssertHasPrimitiveProperty(model, "Count", EdmPrimitiveTypeKind.Int32, isNullable: false); }
public void EntityKeyConvention_FiguresOutTheKeyProperty() { MockType baseType = new MockType("BaseType") .Property<uint>("ID"); ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); builder.AddEntity(baseType); IEdmModel model = builder.GetEdmModel(); IEdmEntityType entity = model.AssertHasEntityType(baseType); entity.AssertHasKey(model, "ID", EdmPrimitiveTypeKind.Int64); }
public void RequiredAttributeEdmPropertyConvention_DoesnotOverwriteExistingConfiguration() { MockType type = new MockType("Entity") .Property(typeof(int), "ID") .Property(typeof(int), "Count", new RequiredAttribute()); ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); builder.AddEntity(type).AddProperty(type.GetProperty("Count")).IsOptional(); IEdmModel model = builder.GetEdmModel(); IEdmEntityType entity = model.AssertHasEntityType(type); entity.AssertHasPrimitiveProperty(model, "Count", EdmPrimitiveTypeKind.Int32, isNullable: true); }
public void EntityKeyConvention_DoesnotFigureOutKeyPropertyIfIgnored() { MockType baseType = new MockType("BaseType") .Property(typeof(int), "ID", new NotMappedAttribute()); ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); builder.AddEntity(baseType); IEdmModel model = builder.GetEdmModel(); IEdmEntityType baseEntity = model.AssertHasEntityType(baseType); Assert.Empty(baseEntity.Properties()); Assert.Empty(baseEntity.Key()); }
public void RequiredAttributeEdmPropertyConvention_ConfiguresRequiredNavigationPropertyAsRequired() { MockType anotherType = new MockType("RelatedEntity") .Property<int>("ID"); MockType type = new MockType("Entity") .Property(typeof(int), "ID") .Property(anotherType, "RelatedEntity", new RequiredAttribute()); ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); builder.AddEntity(type); IEdmModel model = builder.GetEdmModel(); IEdmEntityType entity = model.AssertHasEntityType(type); entity.AssertHasNavigationProperty(model, "RelatedEntity", anotherType, isNullable: false, multiplicity: EdmMultiplicity.One); }
public void ConcurrencyCheckAttributeEdmPropertyConvention_DoesnotOverwriteExistingConfiguration() { MockType type = new MockType("Entity") .Property(typeof(int), "ID") .Property(typeof(int), "Count", new ConcurrencyCheckAttribute()); ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); builder.AddEntity(type).AddProperty(type.GetProperty("Count")).IsOptional(); IEdmModel model = builder.GetEdmModel(); IEdmEntityType entity = model.AssertHasEntityType(type); IEdmStructuralProperty property = entity.AssertHasPrimitiveProperty( model, "Count", EdmPrimitiveTypeKind.Int32, isNullable: true); Assert.Equal(EdmConcurrencyMode.Fixed, property.ConcurrencyMode); }
public void ConcurrencyCheckAttributeEdmPropertyConvention_ConfiguresETagPropertyAsETag() { // Arrange MockType type = new MockType("Entity") .Property(typeof(int), "ID") .Property(typeof(int?), "Count", new ConcurrencyCheckAttribute()); ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); builder.AddEntity(type); // Act IEdmModel model = builder.GetEdmModel(); // Assert IEdmEntityType entity = model.AssertHasEntityType(type); IEdmStructuralProperty property = entity.AssertHasPrimitiveProperty( model, "Count", EdmPrimitiveTypeKind.Int32, isNullable: true); Assert.Equal(EdmConcurrencyMode.Fixed, property.ConcurrencyMode); }
public void DatabaseGeneratedAttributeEdmPropertyConvention_DoesnotOverwriteExistingConfiguration() { // Arrange MockType type = new MockType("Entity") .Property(typeof(int), "ID") .Property(typeof(int?), "Count", new DatabaseGeneratedAttribute(DatabaseGeneratedOption.Computed)); // Act ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); builder.AddEntity(type).AddProperty(type.GetProperty("Count")).IsOptional(); IEdmModel model = builder.GetEdmModel(); // Assert IEdmEntityType entity = model.AssertHasEntityType(type); IEdmStructuralProperty property = entity.AssertHasPrimitiveProperty(model, "Count", EdmPrimitiveTypeKind.Int32, isNullable: true); var idAnnotation = model.GetAnnotationValue<EdmStringConstant>( property, StoreGeneratedPatternAnnotation.AnnotationsNamespace, "StoreGeneratedPattern"); Assert.Null(idAnnotation); }
public void ObjectCollectionsAreIgnoredByDefault(Type propertyType) { MockType type = new MockType("entity") .Property<int>("ID") .Property(propertyType, "Collection"); ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); var entityType = builder.AddEntity(type); builder.AddEntitySet("entityset", entityType); IEdmModel model = builder.GetEdmModel(); Assert.Equal(2, model.SchemaElements.Count()); var entityEdmType = model.AssertHasEntitySet("entityset", type); }
public void OnModelCreating_IsInvoked_AfterConventionsAreRun() { // Arrange MockType entity = new MockType("entity") .Property<int>("ID"); ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); builder.AddEntitySet("entities", builder.AddEntity(entity)); builder.OnModelCreating = (modelBuilder) => { var entityConfiguration = modelBuilder.StructuralTypes.OfType<EntityTypeConfiguration>().Single(); Assert.Equal(1, entityConfiguration.Keys.Count()); var key = entityConfiguration.Keys.Single(); Assert.Equal("ID", key.Name); // mark the key as optional just to verify later. key.OptionalProperty = true; }; // Act IEdmModel model = builder.GetEdmModel(); // Assert Assert.True(model.SchemaElements.OfType<IEdmEntityType>().Single().Key().Single().Type.IsNullable); }
public void MapDerivedTypes_BringsAllDerivedTypes_InTheAssembly() { var mockType1 = new MockType("FooBar"); var mockType2 = new MockType("Foo").BaseType(mockType1); var mockType3 = new MockType("Fo").BaseType(mockType2); var mockType4 = new MockType("Bar").BaseType(mockType1); var mockAssembly = new MockAssembly(mockType1, mockType2, mockType3, mockType4); HttpConfiguration configuration = new HttpConfiguration(); configuration.Services.Replace(typeof(IAssembliesResolver), new TestAssemblyResolver(mockAssembly)); var builder = new ODataConventionModelBuilder(configuration); var entity1 = builder.AddEntity(mockType1); builder.MapDerivedTypes(entity1); Assert.Equal( new[] { "FooBar", "Foo", "Fo", "Bar" }.OrderBy(name => name), builder.StructuralTypes.Select(t => t.Name).OrderBy(name => name)); }
public void ODataConventionModelBuilder_Sets_IsAddedExplicitly_Appropriately() { // Arrange MockType relatedEntity = new MockType("RelatedEntity") .Property<int>("ID"); MockType relatedComplexType = new MockType("RelatedComplexType"); MockType type = new MockType() .Property<int>("ID") .Property<int>("ExplicitlyAddedPrimitive") .Property<int>("InferredPrimitive") .Property<int[]>("ExplicitlyAddedPrimitiveCollection") .Property<int[]>("InferredAddedPrimitiveCollection") .Property(relatedComplexType, "ExplicitlyAddedComplex") .Property(relatedComplexType, "InferredComplex") .Property(relatedComplexType.AsCollection(), "ExplicitlyAddedComplexCollection") .Property(relatedComplexType.AsCollection(), "InferredComplexCollection") .Property(relatedEntity, "ExplicitlyAddedNavigation") .Property(relatedEntity, "InferredNavigation") .Property(relatedEntity.AsCollection(), "ExplicitlyAddedNavigationCollection") .Property(relatedEntity.AsCollection(), "InferredNavigationCollection"); var builder = new ODataConventionModelBuilder(); var entity = builder.AddEntity(type); entity.AddProperty(type.GetProperty("ExplicitlyAddedPrimitive")); entity.AddCollectionProperty(type.GetProperty("ExplicitlyAddedPrimitiveCollection")); entity.AddComplexProperty(type.GetProperty("ExplicitlyAddedComplex")); entity.AddCollectionProperty(type.GetProperty("ExplicitlyAddedComplexCollection")); entity.AddNavigationProperty(type.GetProperty("ExplicitlyAddedNavigation"), EdmMultiplicity.ZeroOrOne); entity.AddNavigationProperty(type.GetProperty("ExplicitlyAddedNavigationCollection"), EdmMultiplicity.Many); builder.OnModelCreating = (b) => { var explicitlyAddedProperties = entity.Properties.Where(p => p.Name.Contains("ExplicitlyAdded")); var inferredProperties = entity.Properties.Where(p => p.Name.Contains("Inferred")); Assert.Equal(13, entity.Properties.Count()); Assert.Equal(6, explicitlyAddedProperties.Count()); Assert.Equal(6, inferredProperties.Count()); foreach (var explicitlyAddedProperty in explicitlyAddedProperties) { Assert.True(explicitlyAddedProperty.AddedExplicitly); } foreach (var inferredProperty in inferredProperties) { Assert.False(inferredProperty.AddedExplicitly); } }; Assert.DoesNotThrow(() => builder.GetEdmModel()); }
public void ModelBuilder_DoesnotThrow_ForEntityCollection(Type collectionType) { var modelBuilder = new ODataConventionModelBuilder(); Type entityType = new MockType("SampleType") .Property<int>("ID") .Property(collectionType, "Products"); modelBuilder.AddEntity(entityType); Assert.DoesNotThrow( () => modelBuilder.GetEdmModel()); }
public void ModelBuilder_SupportsPrimitiveCollection(Type primitiveCollectionPropertyType) { var modelBuilder = new ODataConventionModelBuilder(); Type entityType = new MockType("SampleType") .Property<int>("ID") .Property(primitiveCollectionPropertyType, "Property1"); modelBuilder.AddEntity(entityType); IEdmModel model = modelBuilder.GetEdmModel(); IEdmEntityType entity = model.GetEdmType(entityType) as IEdmEntityType; Assert.NotNull(entity); Assert.Equal(2, entity.DeclaredProperties.Count()); IEdmStructuralProperty property1 = entity.DeclaredProperties.OfType<IEdmStructuralProperty>().SingleOrDefault(p => p.Name == "Property1"); Assert.NotNull(property1); Assert.Equal(EdmTypeKind.Collection, property1.Type.Definition.TypeKind); Assert.Equal(EdmTypeKind.Primitive, (property1.Type.Definition as IEdmCollectionType).ElementType.Definition.TypeKind); }
public void ModelBuilder_DeepChainOfComplexTypes() { var modelBuilder = new ODataConventionModelBuilder(); MockType entityType = new MockType("SampleType") .Property<int>("ID") .Property( new MockType("ComplexType1") .Property( new MockType("ComplexType2") .Property( new MockType("ComplexType3") .Property<int>("Property"), "Property"), "Property"), "Property"); modelBuilder.AddEntity(entityType); var model = modelBuilder.GetEdmModel(); Assert.NotNull(model.FindType("DefaultNamespace.SampleType") as IEdmEntityType); Assert.NotNull(model.FindType("DefaultNamespace.ComplexType1") as IEdmComplexType); Assert.NotNull(model.FindType("DefaultNamespace.ComplexType2") as IEdmComplexType); Assert.NotNull(model.FindType("DefaultNamespace.ComplexType3") as IEdmComplexType); }
public void ComplexType_Containing_EntityCollection_Throws() { MockType entityType = new MockType("EntityType"); MockType complexType = new MockType("ComplexTypeWithEntityCollection") .Property(entityType.AsCollection(), "CollectionProperty"); var modelBuilder = new ODataConventionModelBuilder(); modelBuilder.AddEntity(entityType); modelBuilder.AddComplexType(complexType); Assert.Throws<InvalidOperationException>( () => modelBuilder.GetEdmModel(), "The complex type 'DefaultNamespace.ComplexTypeWithEntityCollection' refers to the entity type 'DefaultNamespace.EntityType' through the property 'CollectionProperty'."); }
public void RemoveBaseTypeProperties_RemovesAllBaseTypePropertiesFromDerivedTypes() { var mockType1 = new MockType("Foo").Property<int>("P1"); var mockType2 = new MockType("Bar").BaseType(mockType1).Property<int>("P1").Property<int>("P2"); var mockType3 = new MockType("FooBar").BaseType(mockType2).Property<int>("P1").Property<int>("P2"); var mockAssembly = new MockAssembly(mockType1, mockType2, mockType3); HttpConfiguration configuration = new HttpConfiguration(); configuration.Services.Replace(typeof(IAssembliesResolver), new TestAssemblyResolver(mockAssembly)); var builder = new ODataConventionModelBuilder(configuration); var entity1 = builder.AddEntity(mockType1); entity1.AddProperty(mockType1.GetProperty("P1")); var entity2 = builder.AddEntity(mockType2).DerivesFrom(entity1); entity2.AddProperty(mockType2.GetProperty("P2")); var entity3 = builder.AddEntity(mockType3); entity3.AddProperty(mockType3.GetProperty("P1")); entity3.AddProperty(mockType3.GetProperty("P2")); builder.RemoveBaseTypeProperties(entity3, entity2); Assert.Empty(entity3.Properties); }
public void CanBuildModelForAnonymousTypes() { Type entityType = new { ID = default(int), NavigationCollection = new[] { new { ID = default(int) } } }.GetType(); ODataConventionModelBuilder builder = new ODataConventionModelBuilder(new HttpConfiguration(), isQueryCompositionMode: true); builder.AddEntitySet("entityset", builder.AddEntity(entityType)); IEdmModel model = builder.GetEdmModel(); IEdmEntityType entity = model.AssertHasEntitySet("entityset", entityType); entity.AssertHasKey(model, "ID", EdmPrimitiveTypeKind.Int32); entity.AssertHasNavigationProperty(model, "NavigationCollection", new { ID = default(int) }.GetType(), isNullable: false, multiplicity: EdmMultiplicity.Many); }
public void ModelBuilder_Doesnot_Override_NavigationPropertyConfiguration() { MockType type1 = new MockType("Entity1") .Property<int>("ID"); MockType type2 = new MockType("Entity2") .Property<int>("ID") .Property(type1, "Relation"); ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); builder.AddEntity(type2).AddNavigationProperty(type2.GetProperty("Relation"), EdmMultiplicity.One); IEdmModel model = builder.GetEdmModel(); IEdmEntityType entity = model.AssertHasEntityType(type2); entity.AssertHasNavigationProperty(model, "Relation", type1, isNullable: false, multiplicity: EdmMultiplicity.One); }
public void EntityType_Containing_ComplexTypeContainingComplexCollection_Works() { Type complexTypeWithComplexCollection = new MockType("ComplexType") .Property<Version[]>("ComplexCollectionProperty"); Type entityType = new MockType("EntityTypeWithComplexCollection") .Property<int>("ID") .Property(complexTypeWithComplexCollection, "ComplexProperty"); var modelBuilder = new ODataConventionModelBuilder(); modelBuilder.AddEntity(entityType); var model = modelBuilder.GetEdmModel(); IEdmEntityType entityEdmType = model.AssertHasEntityType(entityType); model.AssertHasComplexType(typeof(Version)); IEdmComplexType edmComplexType = model.AssertHasComplexType(complexTypeWithComplexCollection); var collectionProperty = edmComplexType.DeclaredProperties.Where(p => p.Name == "ComplexCollectionProperty").SingleOrDefault(); Assert.NotNull(collectionProperty); Assert.True(collectionProperty.Type.IsCollection()); Assert.Equal(collectionProperty.Type.AsCollection().ElementType().FullName(), "System.Version"); }
public void DerivedTypes_Can_DefineKeys_InQueryCompositionMode() { // Arrange MockType baseType = new MockType("BaseType") .Property(typeof(int), "ID"); MockType derivedType = new MockType("DerivedType") .Property(typeof(int), "DerivedTypeId") .BaseType(baseType); MockAssembly assembly = new MockAssembly(baseType, derivedType); HttpConfiguration configuration = new HttpConfiguration(); configuration.Services.Replace(typeof(IAssembliesResolver), new TestAssemblyResolver(assembly)); var builder = new ODataConventionModelBuilder(configuration, isQueryCompositionMode: true); builder.AddEntitySet("bases", builder.AddEntity(baseType)); // Act IEdmModel model = builder.GetEdmModel(); // Assert model.AssertHasEntitySet("bases", baseType); IEdmEntityType baseEntityType = model.AssertHasEntityType(baseType); IEdmEntityType derivedEntityType = model.AssertHasEntityType(derivedType, baseType); baseEntityType.AssertHasKey(model, "ID", EdmPrimitiveTypeKind.Int32); derivedEntityType.AssertHasPrimitiveProperty(model, "DerivedTypeId", EdmPrimitiveTypeKind.Int32, isNullable: false); }
public void GenerateNavigationLink_GeneratesCorrectLink_EvenIfRouteDataPointsToADifferentController() { ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); var orders = builder.AddEntitySet("Orders", builder.AddEntity(typeof(NavigationLinksGenerationConventionTest_Order))); IEdmModel model = builder.GetEdmModel(); var edmEntitySet = model.EntityContainers().Single().EntitySets().Single(); HttpConfiguration configuration = new HttpConfiguration(); configuration.EnableOData(model); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost"); request.Properties[HttpPropertyKeys.HttpConfigurationKey] = configuration; request.Properties[HttpPropertyKeys.HttpRouteDataKey] = new HttpRouteData(new HttpRoute(), new HttpRouteValueDictionary(new { controller = "Customers" })); Uri uri = NavigationLinksGenerationConvention.GenerateNavigationPropertyLink( new EntityInstanceContext { EdmModel = model, EntityInstance = new NavigationLinksGenerationConventionTest_Order { ID = 100 }, EntitySet = edmEntitySet, EntityType = edmEntitySet.ElementType, PathHandler = new DefaultODataPathHandler(model), UrlHelper = request.GetUrlHelper() }, edmEntitySet.ElementType.NavigationProperties().Single(), orders, includeCast: false); Assert.Equal("http://localhost/Orders(100)/Customer", uri.AbsoluteUri); }
public void IgnoredPropertyOnBaseType_DoesnotShowupOnDerivedType() { // Arrange var baseType = new MockType("BaseType") .Property<int>("BaseTypeProperty"); var derivedType = new MockType("DerivedType") .BaseType(baseType) .Property<int>("DerivedTypeProperty"); var mockAssembly = new MockAssembly(baseType, derivedType); HttpConfiguration configuration = new HttpConfiguration(); configuration.Services.Replace(typeof(IAssembliesResolver), new TestAssemblyResolver(mockAssembly)); var builder = new ODataConventionModelBuilder(configuration); // Act var baseEntity = builder.AddEntity(baseType); baseEntity.RemoveProperty(baseType.GetProperty("BaseTypeProperty")); IEdmModel model = builder.GetEdmModel(); // Assert IEdmEntityType baseEntityType = model.AssertHasEntityType(derivedType); Assert.DoesNotContain("BaseTypeProperty", baseEntityType.Properties().Select(p => p.Name)); IEdmEntityType derivedEntityType = model.AssertHasEntityType(derivedType); Assert.DoesNotContain("BaseTypeProperty", derivedEntityType.Properties().Select(p => p.Name)); }
public void ModelBuilder_DerivedComplexTypeHavingKeys_Throws() { MockType baseComplexType = new MockType("BaseComplexType"); MockType derivedComplexType = new MockType("DerivedComplexType") .Property(typeof(int), "DerivedComplexTypeId") .BaseType(baseComplexType); MockType entityType = new MockType("EntityType") .Property(typeof(int), "ID") .Property(baseComplexType.Object, "ComplexProperty"); MockAssembly assembly = new MockAssembly(baseComplexType, derivedComplexType, entityType); HttpConfiguration configuration = new HttpConfiguration(); configuration.Services.Replace(typeof(IAssembliesResolver), new TestAssemblyResolver(assembly)); var builder = new ODataConventionModelBuilder(configuration); builder.AddEntitySet("entities", builder.AddEntity(entityType)); Assert.Throws<InvalidOperationException>( () => builder.GetEdmModel(), "Cannot define keys on type 'DefaultNamespace.DerivedComplexType' deriving from 'DefaultNamespace.BaseComplexType'. Only the root type in the entity inheritance hierarchy can contain keys."); }