/// <summary> /// Initializes a new FunctionImportMappingComposable instance. /// </summary> /// <param name="functionImport">The model function import.</param> /// <param name="targetFunction">The store composable function.</param> /// <param name="resultMapping">The result mapping for the function import.</param> /// <param name="containerMapping">The parent container mapping.</param> public FunctionImportMappingComposable( EdmFunction functionImport, EdmFunction targetFunction, FunctionImportResultMapping resultMapping, EntityContainerMapping containerMapping) : base(Check.NotNull <EdmFunction>(functionImport, nameof(functionImport)), Check.NotNull <EdmFunction>(targetFunction, nameof(targetFunction))) { Check.NotNull <FunctionImportResultMapping>(resultMapping, nameof(resultMapping)); Check.NotNull <EntityContainerMapping>(containerMapping, nameof(containerMapping)); if (!functionImport.IsComposableAttribute) { throw new ArgumentException(Strings.NonComposableFunctionCannotBeMappedAsComposable((object)nameof(functionImport))); } if (!targetFunction.IsComposableAttribute) { throw new ArgumentException(Strings.NonComposableFunctionCannotBeMappedAsComposable((object)nameof(targetFunction))); } EdmType returnType; if (!MetadataHelper.TryGetFunctionImportReturnType <EdmType>(functionImport, 0, out returnType)) { throw new ArgumentException(Strings.InvalidReturnTypeForComposableFunction); } EdmFunction edmFunction = containerMapping.StorageMappingItemCollection != null?containerMapping.StorageMappingItemCollection.StoreItemCollection.ConvertToCTypeFunction(targetFunction) : StoreItemCollection.ConvertFunctionSignatureToCType(targetFunction); RowType tvfReturnType1 = TypeHelpers.GetTvfReturnType(edmFunction); RowType tvfReturnType2 = TypeHelpers.GetTvfReturnType(targetFunction); if (tvfReturnType1 == null) { throw new ArgumentException(Strings.Mapping_FunctionImport_ResultMapping_InvalidSType((object)functionImport.Identity), nameof(functionImport)); } List <EdmSchemaError> parsingErrors = new List <EdmSchemaError>(); FunctionImportMappingComposableHelper composableHelper = new FunctionImportMappingComposableHelper(containerMapping, string.Empty, parsingErrors); FunctionImportMappingComposable mapping; if (Helper.IsStructuralType(returnType)) { composableHelper.TryCreateFunctionImportMappingComposableWithStructuralResult(functionImport, edmFunction, resultMapping.SourceList, tvfReturnType1, tvfReturnType2, (IXmlLineInfo)LineInfo.Empty, out mapping); } else { composableHelper.TryCreateFunctionImportMappingComposableWithScalarResult(functionImport, edmFunction, targetFunction, returnType, tvfReturnType1, (IXmlLineInfo)LineInfo.Empty, out mapping); } if (mapping == null) { throw new InvalidOperationException(parsingErrors.Count > 0 ? parsingErrors[0].Message : string.Empty); } this._containerMapping = mapping._containerMapping; this.m_commandParameters = mapping.m_commandParameters; this.m_structuralTypeMappings = mapping.m_structuralTypeMappings; this.m_targetFunctionKeys = mapping.m_targetFunctionKeys; this._resultMapping = resultMapping; }
public void Can_create_composable_function_import_with_scalar_collection_result() { DbProviderManifest providerManifest; var containerMapping = GetContainerMapping(out providerManifest); var cTypeUsageString = TypeUsage.CreateDefaultTypeUsage( PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String)); var sTypeUsageString = providerManifest.GetStoreType(cTypeUsageString); var rowType = RowType.Create( new[] { EdmProperty.Create("C", sTypeUsageString), }, null); var functionImport = EdmFunction.Create( "F", "N", DataSpace.CSpace, new EdmFunctionPayload { IsComposable = true, ReturnParameters = new[] { FunctionParameter.Create("R", cTypeUsageString.EdmType.GetCollectionType(), ParameterMode.ReturnValue) } }, null); var targetFunction = EdmFunction.Create( "SF", "N", DataSpace.SSpace, new EdmFunctionPayload { IsComposable = true, ReturnParameters = new[] { FunctionParameter.Create("R", rowType.GetCollectionType(), ParameterMode.ReturnValue) } }, null); var resultMapping = new FunctionImportResultMapping(); var functionImportMapping = new FunctionImportMappingComposable( functionImport, targetFunction, resultMapping, containerMapping); Assert.Same(resultMapping, functionImportMapping.ResultMapping); Assert.Null(functionImportMapping.StructuralTypeMappings); Assert.Null(functionImportMapping.TvfKeys); }
public void SetReadOnly_is_called_on_child_mapping_items() { var resultMapping = new FunctionImportResultMapping(); var entityType = new EntityType("E", "N", DataSpace.CSpace); var typeMapping = new FunctionImportEntityTypeMapping( Enumerable.Empty<EntityType>(), new[] { entityType }, new Collection<FunctionImportReturnTypePropertyMapping>(), Enumerable.Empty<FunctionImportEntityTypeMappingCondition>()); resultMapping.AddTypeMapping(typeMapping); Assert.False(typeMapping.IsReadOnly); resultMapping.SetReadOnly(); Assert.True(typeMapping.IsReadOnly); }
public void SetReadOnly_is_called_on_child_mapping_items() { var resultMapping = new FunctionImportResultMapping(); var entityType = new EntityType("E", "N", DataSpace.CSpace); var typeMapping = new FunctionImportEntityTypeMapping( Enumerable.Empty <EntityType>(), new[] { entityType }, new Collection <FunctionImportReturnTypePropertyMapping>(), Enumerable.Empty <FunctionImportEntityTypeMappingCondition>()); resultMapping.AddTypeMapping(typeMapping); Assert.False(typeMapping.IsReadOnly); resultMapping.SetReadOnly(); Assert.True(typeMapping.IsReadOnly); }
public void Cannot_add_type_mapping_if_read_only() { var resultMapping = new FunctionImportResultMapping(); var entityType = new EntityType("E", "N", DataSpace.CSpace); var typeMapping = new FunctionImportEntityTypeMapping( Enumerable.Empty<EntityType>(), new[] { entityType }, new Collection<FunctionImportReturnTypePropertyMapping>(), Enumerable.Empty<FunctionImportEntityTypeMappingCondition>()); resultMapping.SetReadOnly(); Assert.Equal( Strings.OperationOnReadOnlyItem, Assert.Throws<InvalidOperationException>( () => resultMapping.AddTypeMapping(typeMapping)).Message); }
public void Cannot_add_type_mapping_if_read_only() { var resultMapping = new FunctionImportResultMapping(); var entityType = new EntityType("E", "N", DataSpace.CSpace); var typeMapping = new FunctionImportEntityTypeMapping( Enumerable.Empty <EntityType>(), new[] { entityType }, new Collection <FunctionImportReturnTypePropertyMapping>(), Enumerable.Empty <FunctionImportEntityTypeMappingCondition>()); resultMapping.SetReadOnly(); Assert.Equal( Strings.OperationOnReadOnlyItem, Assert.Throws <InvalidOperationException>( () => resultMapping.AddTypeMapping(typeMapping)).Message); }
public void Can_add_get_remove_type_mapping() { var resultMapping = new FunctionImportResultMapping(); Assert.Empty(resultMapping.TypeMappings); var entityType = new EntityType("E", "N", DataSpace.CSpace); var typeMapping = new FunctionImportEntityTypeMapping( Enumerable.Empty <EntityType>(), new[] { entityType }, new Collection <FunctionImportReturnTypePropertyMapping>(), Enumerable.Empty <FunctionImportEntityTypeMappingCondition>()); resultMapping.AddTypeMapping(typeMapping); Assert.Equal(1, resultMapping.TypeMappings.Count); Assert.Same(typeMapping, resultMapping.TypeMappings[0]); resultMapping.RemoveTypeMapping(typeMapping); Assert.Empty(resultMapping.TypeMappings); }
public void Can_add_get_remove_type_mapping() { var resultMapping = new FunctionImportResultMapping(); Assert.Empty(resultMapping.TypeMappings); var entityType = new EntityType("E", "N", DataSpace.CSpace); var typeMapping = new FunctionImportEntityTypeMapping( Enumerable.Empty<EntityType>(), new[] { entityType }, new Collection<FunctionImportReturnTypePropertyMapping>(), Enumerable.Empty<FunctionImportEntityTypeMappingCondition>()); resultMapping.AddTypeMapping(typeMapping); Assert.Equal(1, resultMapping.TypeMappings.Count); Assert.Same(typeMapping, resultMapping.TypeMappings[0]); resultMapping.RemoveTypeMapping(typeMapping); Assert.Empty(resultMapping.TypeMappings); }
public void Can_create_composable_function_import_with_entity_type_collection_result() { DbProviderManifest providerManifest; var containerMapping = GetContainerMapping(out providerManifest); var cTypeUsageInt = TypeUsage.Create( PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32), new[] { Facet.Create(MetadataItem.NullableFacetDescription, false) }); var sTypeUsageInt = TypeUsage.Create( providerManifest.GetStoreType(cTypeUsageInt).EdmType, new[] { Facet.Create(MetadataItem.NullableFacetDescription, false) }); var entityType = EntityType.Create( "RT", "N", DataSpace.CSpace, new[] { "PId" }, new[] { EdmProperty.Create("PId", cTypeUsageInt), EdmProperty.Create("P", cTypeUsageInt), }, null); var rowType = RowType.Create( new[] { EdmProperty.Create("CId", sTypeUsageInt), EdmProperty.Create("C", sTypeUsageInt), }, null); var functionImport = EdmFunction.Create( "F", "N", DataSpace.CSpace, new EdmFunctionPayload { IsComposable = true, ReturnParameters = new[] { FunctionParameter.Create("R", entityType.GetCollectionType(), ParameterMode.ReturnValue) } }, null); var targetFunction = EdmFunction.Create( "SF", "N", DataSpace.SSpace, new EdmFunctionPayload { IsComposable = true, ReturnParameters = new[] { FunctionParameter.Create("R", rowType.GetCollectionType(), ParameterMode.ReturnValue) } }, null); var typeMapping = new FunctionImportEntityTypeMapping( Enumerable.Empty <EntityType>(), new[] { entityType }, new Collection <FunctionImportReturnTypePropertyMapping>() { new FunctionImportReturnTypeScalarPropertyMapping("PId", "CId"), new FunctionImportReturnTypeScalarPropertyMapping("P", "C"), }, Enumerable.Empty <FunctionImportEntityTypeMappingCondition>()); var resultMapping = new FunctionImportResultMapping(); resultMapping.AddTypeMapping(typeMapping); var functionImportMapping = new FunctionImportMappingComposable( functionImport, targetFunction, resultMapping, containerMapping); Assert.Same(resultMapping, functionImportMapping.ResultMapping); Assert.Equal(1, functionImportMapping.StructuralTypeMappings.Count); Assert.Equal(1, functionImportMapping.TvfKeys.Length); Assert.False(resultMapping.IsReadOnly); functionImportMapping.SetReadOnly(); Assert.True(resultMapping.IsReadOnly); }
public void WriteFunctionImportMappingElement_writes_result_mapping_for_non_composable_functions_mapped_explicitly_to_EntityType() { var typeUsage = TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32)); var entityTypeProperty1 = new EdmProperty("ETProperty1", typeUsage); var entityTypeProperty2 = new EdmProperty("ETProperty2", typeUsage); var entityType = new EntityType("ET", "Ns", DataSpace.CSpace); entityType.AddMember(entityTypeProperty1); entityType.AddMember(entityTypeProperty2); var functionImport = new EdmFunction( "f_c", "Ns", DataSpace.CSpace, new EdmFunctionPayload { IsComposable = false, IsFunctionImport = true, ReturnParameters = new[] { new FunctionParameter( "ReturnValue", TypeUsage.CreateDefaultTypeUsage(entityType.GetCollectionType()), ParameterMode.ReturnValue) }, }); typeUsage = ProviderRegistry.Sql2008_ProviderManifest.GetStoreType(typeUsage); var rowTypeProperty1 = new EdmProperty("RTProperty1", typeUsage); var rowTypeProperty2 = new EdmProperty("RTProperty2", typeUsage); var rowType = new RowType(new[] { rowTypeProperty1, rowTypeProperty2 }); var storeFunction = new EdmFunction( "f_s", "Ns.Store", DataSpace.SSpace, new EdmFunctionPayload { IsComposable = false, ReturnParameters = new[] { new FunctionParameter( "Return", TypeUsage.CreateDefaultTypeUsage(rowType), ParameterMode.ReturnValue) }, }); var functionImportResultMapping = new FunctionImportResultMapping(); functionImportResultMapping.AddTypeMapping( new FunctionImportEntityTypeMapping( new EntityType[0], new [] { entityType }, new Collections.ObjectModel.Collection<FunctionImportReturnTypePropertyMapping>() { new FunctionImportReturnTypeScalarPropertyMapping("ETProperty1", "RTProperty1"), new FunctionImportReturnTypeScalarPropertyMapping("ETProperty2", "RTProperty2") }, new FunctionImportEntityTypeMappingCondition[] { new FunctionImportEntityTypeMappingConditionIsNull("RTProperty1", false), new FunctionImportEntityTypeMappingConditionValue("RTProperty2", 4), new FunctionImportEntityTypeMappingConditionValue("FakeCondition", true) } )); var mappingItemCollection = new StorageMappingItemCollection( new EdmItemCollection(EdmModel.CreateConceptualModel()), new StoreItemCollection( EdmModel.CreateStoreModel(ProviderRegistry.Sql2008_ProviderInfo, ProviderRegistry.Sql2008_ProviderManifest)), new string[0]); var containerMapping = new EntityContainerMapping( new EntityContainer("C", DataSpace.CSpace), new EntityContainer("S", DataSpace.SSpace), mappingItemCollection, false); var functionImportMapping = new FunctionImportMappingNonComposable( functionImport, storeFunction, new [] { functionImportResultMapping }, containerMapping); containerMapping.AddFunctionImportMapping(functionImportMapping); var fixture = new Fixture(); fixture.Writer.WriteFunctionImportMappingElement(functionImportMapping); Assert.Equal( @"<FunctionImportMapping FunctionName=""Ns.Store.f_s"" FunctionImportName=""f_c""> <ResultMapping> <EntityTypeMapping TypeName=""Ns.ET""> <ScalarProperty Name=""ETProperty1"" ColumnName=""RTProperty1"" /> <ScalarProperty Name=""ETProperty2"" ColumnName=""RTProperty2"" /> <Condition ColumnName=""RTProperty1"" IsNull=""false"" /> <Condition ColumnName=""RTProperty2"" Value=""4"" /> <Condition ColumnName=""FakeCondition"" Value=""1"" /> </EntityTypeMapping> </ResultMapping> </FunctionImportMapping>", fixture.ToString()); }
/// <summary> /// Initializes a new FunctionImportMappingComposable instance. /// </summary> /// <param name="functionImport">The model function import.</param> /// <param name="targetFunction">The store composable function.</param> /// <param name="resultMapping">The result mapping for the function import.</param> /// <param name="containerMapping">The parent container mapping.</param> public FunctionImportMappingComposable( EdmFunction functionImport, EdmFunction targetFunction, FunctionImportResultMapping resultMapping, EntityContainerMapping containerMapping) : base( Check.NotNull(functionImport, "functionImport"), Check.NotNull(targetFunction, "targetFunction")) { Check.NotNull(resultMapping, "resultMapping"); Check.NotNull(containerMapping, "containerMapping"); if (!functionImport.IsComposableAttribute) { throw new ArgumentException(Strings.NonComposableFunctionCannotBeMappedAsComposable("functionImport")); } if (!targetFunction.IsComposableAttribute) { throw new ArgumentException(Strings.NonComposableFunctionCannotBeMappedAsComposable("targetFunction")); } if (functionImport.EntitySet != null) { throw new NotSupportedException(Strings.ComposableFunctionImportsReturningEntitiesNotSupported); } EdmType resultType; if (!MetadataHelper.TryGetFunctionImportReturnType(functionImport, 0, out resultType)) { throw new ArgumentException(Strings.InvalidReturnTypeForComposableFunction); } // Function mapping is allowed only for TVFs on the s-space. var cTypeTargetFunction = containerMapping.StorageMappingItemCollection.StoreItemCollection.ConvertToCTypeFunction(targetFunction); var cTypeTvfElementType = TypeHelpers.GetTvfReturnType(cTypeTargetFunction); var sTypeTvfElementType = TypeHelpers.GetTvfReturnType(targetFunction); if (cTypeTvfElementType == null) { Debug.Assert(sTypeTvfElementType == null); throw new ArgumentException( Strings.Mapping_FunctionImport_ResultMapping_InvalidSType(functionImport.Identity), "functionImport"); } var errors = new List <EdmSchemaError>(); var functionImportHelper = new FunctionImportMappingComposableHelper( containerMapping, String.Empty, errors); FunctionImportMappingComposable mapping; if (Helper.IsStructuralType(resultType)) { functionImportHelper.TryCreateFunctionImportMappingComposableWithStructuralResult( functionImport, cTypeTargetFunction, resultMapping.SourceList, cTypeTvfElementType, sTypeTvfElementType, LineInfo.Empty, out mapping); } else { Debug.Assert(TypeSemantics.IsScalarType(resultType)); Debug.Assert(resultMapping.TypeMappings.Count == 0); functionImportHelper.TryCreateFunctionImportMappingComposableWithScalarResult( functionImport, cTypeTargetFunction, targetFunction, resultType, cTypeTvfElementType, LineInfo.Empty, out mapping); } if (mapping == null) { throw new InvalidOperationException(errors.Count > 0 ? errors[0].Message : String.Empty); } _containerMapping = mapping._containerMapping; m_commandParameters = mapping.m_commandParameters; m_structuralTypeMappings = mapping.m_structuralTypeMappings; m_targetFunctionKeys = mapping.m_targetFunctionKeys; _resultMapping = resultMapping; }
public void Can_create_composable_function_import_with_entity_type_collection_result() { DbProviderManifest providerManifest; var containerMapping = GetContainerMapping(out providerManifest); var cTypeUsageInt = TypeUsage.Create( PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32), new[] { Facet.Create(MetadataItem.NullableFacetDescription, false) }); var sTypeUsageInt = TypeUsage.Create( providerManifest.GetStoreType(cTypeUsageInt).EdmType, new[] { Facet.Create(MetadataItem.NullableFacetDescription, false) }); var entityType = EntityType.Create( "RT", "N", DataSpace.CSpace, new[] { "PId" }, new[] { EdmProperty.Create("PId", cTypeUsageInt), EdmProperty.Create("P", cTypeUsageInt), }, null); var rowType = RowType.Create( new[] { EdmProperty.Create("CId", sTypeUsageInt), EdmProperty.Create("C", sTypeUsageInt), }, null); var functionImport = EdmFunction.Create( "F", "N", DataSpace.CSpace, new EdmFunctionPayload { IsComposable = true, ReturnParameters = new[] { FunctionParameter.Create("R", entityType.GetCollectionType(), ParameterMode.ReturnValue) } }, null); var targetFunction = EdmFunction.Create( "SF", "N", DataSpace.SSpace, new EdmFunctionPayload { IsComposable = true, ReturnParameters = new[] { FunctionParameter.Create("R", rowType.GetCollectionType(), ParameterMode.ReturnValue) } }, null); var typeMapping = new FunctionImportEntityTypeMapping( Enumerable.Empty<EntityType>(), new[] { entityType }, new Collection<FunctionImportReturnTypePropertyMapping>() { new FunctionImportReturnTypeScalarPropertyMapping("PId", "CId"), new FunctionImportReturnTypeScalarPropertyMapping("P", "C"), }, Enumerable.Empty<FunctionImportEntityTypeMappingCondition>()); var resultMapping = new FunctionImportResultMapping(); resultMapping.AddTypeMapping(typeMapping); var functionImportMapping = new FunctionImportMappingComposable( functionImport, targetFunction, resultMapping, containerMapping); Assert.Same(resultMapping, functionImportMapping.ResultMapping); Assert.Equal(1, functionImportMapping.StructuralTypeMappings.Count); Assert.Equal(1, functionImportMapping.TvfKeys.Length); Assert.False(resultMapping.IsReadOnly); functionImportMapping.SetReadOnly(); Assert.True(resultMapping.IsReadOnly); }
private void WriteFunctionImportResultMappingElement(FunctionImportResultMapping resultMapping) { DebugCheck.NotNull(resultMapping); _xmlWriter.WriteStartElement(MslConstructs.FunctionImportMappingResultMapping); foreach (var typeMapping in resultMapping.TypeMappings) { var entityTypeMapping = typeMapping as FunctionImportEntityTypeMapping; if (entityTypeMapping != null) { WriteFunctionImportEntityTypeMappingElement(entityTypeMapping); } else { Debug.Assert(typeMapping is FunctionImportComplexTypeMapping, "Unexpected mapping kind."); WriteFunctionImportComplexTypeMappingElement((FunctionImportComplexTypeMapping)typeMapping); } } _xmlWriter.WriteEndElement(); }
/// <summary> /// Initializes a new FunctionImportMappingComposable instance. /// </summary> /// <param name="functionImport">The model function import.</param> /// <param name="targetFunction">The store composable function.</param> /// <param name="resultMapping">The result mapping for the function import.</param> /// <param name="containerMapping">The parent container mapping.</param> public FunctionImportMappingComposable( EdmFunction functionImport, EdmFunction targetFunction, FunctionImportResultMapping resultMapping, EntityContainerMapping containerMapping) : base( Check.NotNull(functionImport, "functionImport"), Check.NotNull(targetFunction, "targetFunction")) { Check.NotNull(resultMapping, "resultMapping"); Check.NotNull(containerMapping, "containerMapping"); if (!functionImport.IsComposableAttribute) { throw new ArgumentException(Strings.NonComposableFunctionCannotBeMappedAsComposable("functionImport")); } if (!targetFunction.IsComposableAttribute) { throw new ArgumentException(Strings.NonComposableFunctionCannotBeMappedAsComposable("targetFunction")); } EdmType resultType; if (!MetadataHelper.TryGetFunctionImportReturnType(functionImport, 0, out resultType)) { throw new ArgumentException(Strings.InvalidReturnTypeForComposableFunction); } // when this method is invoked when a CodeFirst model is being built (e.g. from a custom convention) the // StorageMappingItemCollection will be null. In this case we can call the converting method directly which // will return the correct result but the result won't be memoized. This however does not matter at this // point since the model is still being constructed. var cTypeTargetFunction = containerMapping.StorageMappingItemCollection != null ? containerMapping.StorageMappingItemCollection.StoreItemCollection.ConvertToCTypeFunction(targetFunction) : StoreItemCollection.ConvertFunctionSignatureToCType(targetFunction); var cTypeTvfElementType = TypeHelpers.GetTvfReturnType(cTypeTargetFunction); var sTypeTvfElementType = TypeHelpers.GetTvfReturnType(targetFunction); if (cTypeTvfElementType == null) { Debug.Assert(sTypeTvfElementType == null); throw new ArgumentException( Strings.Mapping_FunctionImport_ResultMapping_InvalidSType(functionImport.Identity), "functionImport"); } var errors = new List<EdmSchemaError>(); var functionImportHelper = new FunctionImportMappingComposableHelper( containerMapping, String.Empty, errors); FunctionImportMappingComposable mapping; if (Helper.IsStructuralType(resultType)) { functionImportHelper.TryCreateFunctionImportMappingComposableWithStructuralResult( functionImport, cTypeTargetFunction, resultMapping.SourceList, cTypeTvfElementType, sTypeTvfElementType, LineInfo.Empty, out mapping); } else { Debug.Assert(TypeSemantics.IsScalarType(resultType)); Debug.Assert(resultMapping.TypeMappings.Count == 0); functionImportHelper.TryCreateFunctionImportMappingComposableWithScalarResult( functionImport, cTypeTargetFunction, targetFunction, resultType, cTypeTvfElementType, LineInfo.Empty, out mapping); } if (mapping == null) { throw new InvalidOperationException(errors.Count > 0 ? errors[0].Message : String.Empty); } _containerMapping = mapping._containerMapping; m_commandParameters = mapping.m_commandParameters; m_structuralTypeMappings = mapping.m_structuralTypeMappings; m_targetFunctionKeys = mapping.m_targetFunctionKeys; _resultMapping = resultMapping; }
public void Can_create_composable_function_import_with_entity_type_hierarchy() { DbProviderManifest providerManifest; var containerMapping = GetContainerMapping(out providerManifest); var cTypeUsageInt = TypeUsage.Create( PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32), new[] { Facet.Create(MetadataItem.NullableFacetDescription, false) }); var sTypeUsageInt = TypeUsage.Create( providerManifest.GetStoreType(cTypeUsageInt).EdmType, new[] { Facet.Create(MetadataItem.NullableFacetDescription, false) }); var cTypeUsageString = TypeUsage.CreateDefaultTypeUsage( PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String)); var sTypeUsageString = providerManifest.GetStoreType(cTypeUsageString); var itemCollection = containerMapping.StorageMappingItemCollection.EdmItemCollection.GetItems<EntityType>(); var baseEntityType = itemCollection.Single(et => et.Name == "E"); var entityType1 = itemCollection.Single(et => et.Name == "E1"); var entityType2 = itemCollection.Single(et => et.Name == "E2"); var rowType = RowType.Create( new[] { EdmProperty.Create("CId", sTypeUsageInt), EdmProperty.Create("C", sTypeUsageString), EdmProperty.Create("C1", sTypeUsageString), EdmProperty.Create("C2", sTypeUsageString), EdmProperty.Create("CD", sTypeUsageString) }, null); var functionImport = EdmFunction.Create( "F", "N", DataSpace.CSpace, new EdmFunctionPayload { IsComposable = true, ReturnParameters = new[] { FunctionParameter.Create("R", baseEntityType.GetCollectionType(), ParameterMode.ReturnValue) } }, null); var targetFunction = EdmFunction.Create( "SF", "N", DataSpace.SSpace, new EdmFunctionPayload { IsComposable = true, ReturnParameters = new[] { FunctionParameter.Create("R", rowType.GetCollectionType(), ParameterMode.ReturnValue) } }, null); var resultMapping = new FunctionImportResultMapping(); var typeMapping = new FunctionImportEntityTypeMapping( new[] { baseEntityType }, Enumerable.Empty<EntityType>(), new Collection<FunctionImportReturnTypePropertyMapping>() { new FunctionImportReturnTypeScalarPropertyMapping("Id", "CId"), new FunctionImportReturnTypeScalarPropertyMapping("P", "C"), new FunctionImportReturnTypeScalarPropertyMapping("Discriminator", "CD"), }, Enumerable.Empty<FunctionImportEntityTypeMappingConditionValue>()); resultMapping.AddTypeMapping(typeMapping); typeMapping = new FunctionImportEntityTypeMapping( Enumerable.Empty<EntityType>(), new[] { entityType1 }, new Collection<FunctionImportReturnTypePropertyMapping>() { new FunctionImportReturnTypeScalarPropertyMapping("P1", "C1"), }, new [] { new FunctionImportEntityTypeMappingConditionValue("CD", "E1") }); resultMapping.AddTypeMapping(typeMapping); typeMapping = new FunctionImportEntityTypeMapping( Enumerable.Empty<EntityType>(), new[] { entityType2 }, new Collection<FunctionImportReturnTypePropertyMapping>() { new FunctionImportReturnTypeScalarPropertyMapping("P2", "C2"), }, new [] { new FunctionImportEntityTypeMappingConditionValue("CD", "E2") }); resultMapping.AddTypeMapping(typeMapping); var functionImportMapping = new FunctionImportMappingComposable( functionImport, targetFunction, resultMapping, containerMapping); Assert.Same(resultMapping, functionImportMapping.ResultMapping); Assert.Equal(2, functionImportMapping.StructuralTypeMappings.Count); Assert.Equal(1, functionImportMapping.TvfKeys.Length); Assert.Equal(typeof(E1).Name, functionImportMapping.StructuralTypeMappings[0].Item1.Name); Assert.Equal(1, functionImportMapping.StructuralTypeMappings[0].Item2.Count()); Assert.Equal(3, functionImportMapping.StructuralTypeMappings[0].Item3.Count()); Assert.Equal(typeof(E2).Name, functionImportMapping.StructuralTypeMappings[1].Item1.Name); Assert.Equal(1, functionImportMapping.StructuralTypeMappings[0].Item2.Count()); Assert.Equal(3, functionImportMapping.StructuralTypeMappings[0].Item3.Count()); }
public void Can_create_composable_function_import_with_entity_type_hierarchy() { DbProviderManifest providerManifest; var containerMapping = GetContainerMapping(out providerManifest); var cTypeUsageInt = TypeUsage.Create( PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32), new[] { Facet.Create(MetadataItem.NullableFacetDescription, false) }); var sTypeUsageInt = TypeUsage.Create( providerManifest.GetStoreType(cTypeUsageInt).EdmType, new[] { Facet.Create(MetadataItem.NullableFacetDescription, false) }); var cTypeUsageString = TypeUsage.CreateDefaultTypeUsage( PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String)); var sTypeUsageString = providerManifest.GetStoreType(cTypeUsageString); var itemCollection = containerMapping.StorageMappingItemCollection.EdmItemCollection.GetItems <EntityType>(); var baseEntityType = itemCollection.Single(et => et.Name == "E"); var entityType1 = itemCollection.Single(et => et.Name == "E1"); var entityType2 = itemCollection.Single(et => et.Name == "E2"); var rowType = RowType.Create( new[] { EdmProperty.Create("CId", sTypeUsageInt), EdmProperty.Create("C", sTypeUsageString), EdmProperty.Create("C1", sTypeUsageString), EdmProperty.Create("C2", sTypeUsageString), EdmProperty.Create("CD", sTypeUsageString) }, null); var functionImport = EdmFunction.Create( "F", "N", DataSpace.CSpace, new EdmFunctionPayload { IsComposable = true, ReturnParameters = new[] { FunctionParameter.Create("R", baseEntityType.GetCollectionType(), ParameterMode.ReturnValue) } }, null); var targetFunction = EdmFunction.Create( "SF", "N", DataSpace.SSpace, new EdmFunctionPayload { IsComposable = true, ReturnParameters = new[] { FunctionParameter.Create("R", rowType.GetCollectionType(), ParameterMode.ReturnValue) } }, null); var resultMapping = new FunctionImportResultMapping(); var typeMapping = new FunctionImportEntityTypeMapping( new[] { baseEntityType }, Enumerable.Empty <EntityType>(), new Collection <FunctionImportReturnTypePropertyMapping>() { new FunctionImportReturnTypeScalarPropertyMapping("Id", "CId"), new FunctionImportReturnTypeScalarPropertyMapping("P", "C"), new FunctionImportReturnTypeScalarPropertyMapping("Discriminator", "CD"), }, Enumerable.Empty <FunctionImportEntityTypeMappingConditionValue>()); resultMapping.AddTypeMapping(typeMapping); typeMapping = new FunctionImportEntityTypeMapping( Enumerable.Empty <EntityType>(), new[] { entityType1 }, new Collection <FunctionImportReturnTypePropertyMapping>() { new FunctionImportReturnTypeScalarPropertyMapping("P1", "C1"), }, new [] { new FunctionImportEntityTypeMappingConditionValue("CD", "E1") }); resultMapping.AddTypeMapping(typeMapping); typeMapping = new FunctionImportEntityTypeMapping( Enumerable.Empty <EntityType>(), new[] { entityType2 }, new Collection <FunctionImportReturnTypePropertyMapping>() { new FunctionImportReturnTypeScalarPropertyMapping("P2", "C2"), }, new [] { new FunctionImportEntityTypeMappingConditionValue("CD", "E2") }); resultMapping.AddTypeMapping(typeMapping); var functionImportMapping = new FunctionImportMappingComposable( functionImport, targetFunction, resultMapping, containerMapping); Assert.Same(resultMapping, functionImportMapping.ResultMapping); Assert.Equal(2, functionImportMapping.StructuralTypeMappings.Count); Assert.Equal(1, functionImportMapping.TvfKeys.Length); Assert.Equal(typeof(E1).Name, functionImportMapping.StructuralTypeMappings[0].Item1.Name); Assert.Equal(1, functionImportMapping.StructuralTypeMappings[0].Item2.Count()); Assert.Equal(3, functionImportMapping.StructuralTypeMappings[0].Item3.Count()); Assert.Equal(typeof(E2).Name, functionImportMapping.StructuralTypeMappings[1].Item1.Name); Assert.Equal(1, functionImportMapping.StructuralTypeMappings[0].Item2.Count()); Assert.Equal(3, functionImportMapping.StructuralTypeMappings[0].Item3.Count()); }
/// <summary> /// Initializes a new FunctionImportMappingComposable instance. /// </summary> /// <param name="functionImport">The model function import.</param> /// <param name="targetFunction">The store composable function.</param> /// <param name="resultMapping">The result mapping for the function import.</param> /// <param name="containerMapping">The parent container mapping.</param> public FunctionImportMappingComposable( EdmFunction functionImport, EdmFunction targetFunction, FunctionImportResultMapping resultMapping, EntityContainerMapping containerMapping) : base( Check.NotNull(functionImport, "functionImport"), Check.NotNull(targetFunction, "targetFunction")) { Check.NotNull(resultMapping, "resultMapping"); Check.NotNull(containerMapping, "containerMapping"); if (!functionImport.IsComposableAttribute) { throw new ArgumentException(Strings.NonComposableFunctionCannotBeMappedAsComposable("functionImport")); } if (!targetFunction.IsComposableAttribute) { throw new ArgumentException(Strings.NonComposableFunctionCannotBeMappedAsComposable("targetFunction")); } EdmType resultType; if (!MetadataHelper.TryGetFunctionImportReturnType(functionImport, 0, out resultType)) { throw new ArgumentException(Strings.InvalidReturnTypeForComposableFunction); } // when this method is invoked when a CodeFirst model is being built (e.g. from a custom convention) the // StorageMappingItemCollection will be null. In this case we can call the converting method directly which // will return the correct result but the result won't be memoized. This however does not matter at this // point since the model is still being constructed. var cTypeTargetFunction = containerMapping.StorageMappingItemCollection != null ? containerMapping.StorageMappingItemCollection.StoreItemCollection.ConvertToCTypeFunction(targetFunction) : StoreItemCollection.ConvertFunctionSignatureToCType(targetFunction); var cTypeTvfElementType = TypeHelpers.GetTvfReturnType(cTypeTargetFunction); var sTypeTvfElementType = TypeHelpers.GetTvfReturnType(targetFunction); if (cTypeTvfElementType == null) { Debug.Assert(sTypeTvfElementType == null); throw new ArgumentException( Strings.Mapping_FunctionImport_ResultMapping_InvalidSType(functionImport.Identity), "functionImport"); } var errors = new List <EdmSchemaError>(); var functionImportHelper = new FunctionImportMappingComposableHelper( containerMapping, String.Empty, errors); FunctionImportMappingComposable mapping; if (Helper.IsStructuralType(resultType)) { functionImportHelper.TryCreateFunctionImportMappingComposableWithStructuralResult( functionImport, cTypeTargetFunction, resultMapping.SourceList, cTypeTvfElementType, sTypeTvfElementType, LineInfo.Empty, out mapping); } else { Debug.Assert(TypeSemantics.IsScalarType(resultType)); Debug.Assert(resultMapping.TypeMappings.Count == 0); functionImportHelper.TryCreateFunctionImportMappingComposableWithScalarResult( functionImport, cTypeTargetFunction, targetFunction, resultType, cTypeTvfElementType, LineInfo.Empty, out mapping); } if (mapping == null) { throw new InvalidOperationException(errors.Count > 0 ? errors[0].Message : String.Empty); } _containerMapping = mapping._containerMapping; m_commandParameters = mapping.m_commandParameters; m_structuralTypeMappings = mapping.m_structuralTypeMappings; m_targetFunctionKeys = mapping.m_targetFunctionKeys; _resultMapping = resultMapping; }
public void Can_create_composable_function_import_with_complex_type_collection_result() { DbProviderManifest providerManifest; var containerMapping = GetContainerMapping(out providerManifest); var cTypeUsageString = TypeUsage.CreateDefaultTypeUsage( PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String)); var sTypeUsageString = providerManifest.GetStoreType(cTypeUsageString); var complexType = ComplexType.Create( "RT", "N", DataSpace.CSpace, new[] { EdmProperty.Create("P1", cTypeUsageString), EdmProperty.Create("P2", cTypeUsageString) }, null); var rowType = RowType.Create( new[] { EdmProperty.Create("C1", sTypeUsageString), EdmProperty.Create("C2", sTypeUsageString) }, null); var functionImport = EdmFunction.Create( "F", "N", DataSpace.CSpace, new EdmFunctionPayload { IsComposable = true, ReturnParameters = new[] { FunctionParameter.Create("R", complexType.GetCollectionType(), ParameterMode.ReturnValue) } }, null); var targetFunction = EdmFunction.Create( "SF", "N", DataSpace.SSpace, new EdmFunctionPayload { IsComposable = true, ReturnParameters = new[] { FunctionParameter.Create("R", rowType.GetCollectionType(), ParameterMode.ReturnValue) } }, null); var typeMapping = new FunctionImportComplexTypeMapping( complexType, new Collection<FunctionImportReturnTypePropertyMapping>() { new FunctionImportReturnTypeScalarPropertyMapping("P1", "C1"), new FunctionImportReturnTypeScalarPropertyMapping("P2", "C2"), }); var resultMapping = new FunctionImportResultMapping(); resultMapping.AddTypeMapping(typeMapping); var functionImportMapping = new FunctionImportMappingComposable( functionImport, targetFunction, resultMapping, containerMapping); Assert.Same(resultMapping, functionImportMapping.ResultMapping); Assert.Equal(1, functionImportMapping.StructuralTypeMappings.Count); Assert.Null(functionImportMapping.TvfKeys); }