/// <summary> /// Creates a column map for the given reader and function mapping. /// </summary> internal virtual CollectionColumnMap CreateFunctionImportStructuralTypeColumnMap( DbDataReader storeDataReader, FunctionImportMappingNonComposable mapping, int resultSetIndex, EntitySet entitySet, StructuralType baseStructuralType) { var resultMapping = mapping.GetResultMapping(resultSetIndex); Debug.Assert(resultMapping != null); if (resultMapping.NormalizedEntityTypeMappings.Count == 0) // no explicit mapping; use default non-polymorphic reader { // if there is no mapping, create default mapping to root entity type or complex type Debug.Assert(!baseStructuralType.Abstract, "mapping loader must verify abstract types have explicit mapping"); return CreateColumnMapFromReaderAndType( storeDataReader, baseStructuralType, entitySet, resultMapping.ReturnTypeColumnsRenameMapping); } // the section below deals with the polymorphic entity type mapping for return type var baseEntityType = baseStructuralType as EntityType; Debug.Assert(null != baseEntityType, "We should have entity type here"); // Generate column maps for all discriminators var discriminatorColumns = CreateDiscriminatorColumnMaps(storeDataReader, mapping, resultSetIndex); // Generate default maps for all mapped entity types var mappedEntityTypes = new HashSet<EntityType>(resultMapping.MappedEntityTypes); mappedEntityTypes.Add(baseEntityType); // make sure the base type is represented var typeChoices = new Dictionary<EntityType, TypedColumnMap>(mappedEntityTypes.Count); ColumnMap[] baseTypeColumnMaps = null; foreach (var entityType in mappedEntityTypes) { var propertyColumnMaps = GetColumnMapsForType(storeDataReader, entityType, resultMapping.ReturnTypeColumnsRenameMapping); var entityColumnMap = CreateEntityTypeElementColumnMap( storeDataReader, entityType, entitySet, propertyColumnMaps, resultMapping.ReturnTypeColumnsRenameMapping); if (!entityType.Abstract) { typeChoices.Add(entityType, entityColumnMap); } if (entityType == baseStructuralType) { baseTypeColumnMaps = propertyColumnMaps; } } // NOTE: We don't have a null sentinel here, because the stored proc won't // return one anyway; we'll just presume the data's always there. var polymorphicMap = new MultipleDiscriminatorPolymorphicColumnMap( TypeUsage.Create(baseStructuralType), baseStructuralType.Name, baseTypeColumnMaps, discriminatorColumns, typeChoices, (object[] discriminatorValues) => mapping.Discriminate(discriminatorValues, resultSetIndex)); CollectionColumnMap collection = new SimpleCollectionColumnMap( baseStructuralType.GetCollectionType().TypeUsage, baseStructuralType.Name, polymorphicMap, null, null); return collection; }
private static void SetupFooFunction(MetadataWorkspace metadataWorkspace) { var metadataWorkspaceMock = Mock.Get(metadataWorkspace); var entityType = (EdmType)new EntityType( "ReturnedEntity", "FooNamespace", DataSpace.CSpace, new[] { "key" }, new EdmMember[] { new EdmProperty("key") }); var collectionTypeMock = new Mock<CollectionType>(entityType) { CallBase = true }; metadataWorkspaceMock.Setup(m => m.TryDetermineCSpaceModelType(It.IsAny<Type>(), out entityType)) .Returns(true); var entityContainer = new EntityContainer("Bar", DataSpace.CSpace); metadataWorkspaceMock.Setup(m => m.TryGetEntityContainer(It.IsAny<string>(), It.IsAny<DataSpace>(), out entityContainer)) .Returns(true); var functionImport = new EdmFunction( "Foo", "Bar", DataSpace.CSpace, new EdmFunctionPayload { IsComposable = false, IsFunctionImport = true, ReturnParameters = new[] { new FunctionParameter( EdmConstants.ReturnType, TypeUsage.Create(collectionTypeMock.Object), ParameterMode.ReturnValue), } }); entityContainer.AddFunctionImport(functionImport); entityContainer.AddEntitySetBase(new EntitySet("Foo", "", "", "", (EntityType)entityType)); var edmItemCollection = (EdmItemCollection)metadataWorkspace.GetItemCollection(DataSpace.CSpace); var storeItemCollection = (StoreItemCollection)metadataWorkspace.GetItemCollection(DataSpace.SSpace); var containerMappingMock = new Mock<EntityContainerMapping>(entityContainer); FunctionImportMapping targetFunctionMapping = new FunctionImportMappingNonComposable( functionImport, functionImport, new List<List<FunctionImportStructuralTypeMapping>>(), edmItemCollection); containerMappingMock.Setup( m => m.TryGetFunctionImportMapping( It.IsAny<EdmFunction>(), out targetFunctionMapping)).Returns(true); var storageMappingItemCollection = new Mock<StorageMappingItemCollection>( edmItemCollection, storeItemCollection, new string[0]) { CallBase = true }; storageMappingItemCollection.Setup(m => m.GetItems<EntityContainerMapping>()) .Returns( new ReadOnlyCollection<EntityContainerMapping>( new List<EntityContainerMapping> { containerMappingMock.Object })); metadataWorkspaceMock.Setup(m => m.GetItemCollection(DataSpace.CSSpace, It.IsAny<bool>())) .Returns(storageMappingItemCollection.Object); }
public static void AddFunction( this DbModel model, MethodInfo methodInfo, FunctionAttribute functionAttribute) { if (model == null) { throw new ArgumentNullException(nameof(model)); } if (methodInfo == null) { throw new ArgumentNullException(nameof(methodInfo)); } if (functionAttribute == null) { throw new ArgumentNullException(nameof(functionAttribute)); } /* <!-- SSDL content --> <edmx:StorageModels> <Schema Namespace="CodeFirstDatabaseSchema" Provider="System.Data.SqlClient" ProviderManifestToken="2012" Alias="Self" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns:customannotation="http://schemas.microsoft.com/ado/2013/11/edm/customannotation" xmlns="http://schemas.microsoft.com/ado/2009/11/edm/ssdl"> <Function Name="ufnGetContactInformation" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="true" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo"> <Parameter Name="PersonID" Type="int" Mode="In" /> <ReturnType> <CollectionType> <RowType> <Property Name="PersonID" Type="int" Nullable="false" /> <Property Name="FirstName" Type="nvarchar" MaxLength="50" /> <Property Name="LastName" Type="nvarchar" MaxLength="50" /> <Property Name="JobTitle" Type="nvarchar" MaxLength="50" /> <Property Name="BusinessEntityType" Type="nvarchar" MaxLength="50" /> </RowType> </CollectionType> </ReturnType> </Function> <Function Name="ufnGetProductListPrice" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="true" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo" ReturnType="money"> <Parameter Name="ProductID" Type="int" Mode="In" /> <Parameter Name="OrderDate" Type="datetime" Mode="In" /> </Function> <Function Name="ufnGetProductStandardCost" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="false" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo"> <Parameter Name="ProductID" Type="int" Mode="In" /> <Parameter Name="OrderDate" Type="datetime" Mode="In" /> <CommandText> SELECT [dbo].[ufnGetProductListPrice](@ProductID, @OrderDate) </CommandText> </Function> <Function Name="uspGetCategoryAndSubCategory" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="false" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo"> <Parameter Name="CategoryID" Type="int" Mode="In" /> </Function> <Function Name="uspGetManagerEmployees" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="false" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo"> <Parameter Name="BusinessEntityID" Type="int" Mode="In" /> </Function> <EntityContainer Name="CodeFirstDatabase"> </EntityContainer> </Schema> </edmx:StorageModels> */ // Build above <StorageModels> imperatively. string functionName = functionAttribute.FunctionName; if (string.IsNullOrWhiteSpace(functionName)) { functionName = methodInfo.Name; } EdmFunction storeFunction = EdmFunction.Create( functionName, CodeFirstDatabaseSchema, // model.StoreModel.Container.Name is "CodeFirstDatabase". DataSpace.SSpace, // <edmx:StorageModels> new EdmFunctionPayload() { Schema = functionAttribute.Schema, IsAggregate = functionAttribute.IsAggregate, IsBuiltIn = functionAttribute.IsBuiltIn, IsNiladic = functionAttribute.IsNiladic, IsComposable = functionAttribute.IsComposable, ParameterTypeSemantics = functionAttribute.ParameterTypeSemantics, Parameters = model.GetStoreParameters(methodInfo, functionAttribute), ReturnParameters = model.GetStoreReturnParameters(methodInfo, functionAttribute), CommandText = methodInfo.GetStoreCommandText(functionAttribute, functionName) }, null); model.StoreModel.AddItem(storeFunction); switch (functionAttribute.Type) { // Aggregate/Built in/Niladic/Composable scalar-valued function has no <FunctionImport> or <FunctionImportMapping>. case FunctionType.ComposableScalarValuedFunction: case FunctionType.AggregateFunction: case FunctionType.BuiltInFunction: case FunctionType.NiladicFunction: return; } /* <!-- CSDL content --> <edmx:ConceptualModels> <Schema Namespace="AdventureWorks" Alias="Self" annotation:UseStrongSpatialTypes="false" xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" xmlns:customannotation="http://schemas.microsoft.com/ado/2013/11/edm/customannotation" xmlns="http://schemas.microsoft.com/ado/2009/11/edm"> <EntityContainer Name="AdventureWorks" annotation:LazyLoadingEnabled="true"> <FunctionImport Name="ufnGetContactInformation" IsComposable="true" ReturnType="Collection(AdventureWorks.ContactInformation)"> <Parameter Name="PersonID" Mode="In" Type="Int32" /> </FunctionImport> <FunctionImport Name="uspGetCategoryAndSubCategory" ReturnType="Collection(AdventureWorks.CategoryAndSubCategory)"> <Parameter Name="CategoryID" Mode="In" Type="Int32" /> </FunctionImport> <FunctionImport Name="uspGetManagerEmployees" ReturnType="Collection(AdventureWorks.ManagerEmployee)"> <Parameter Name="BusinessEntityID" Mode="In" Type="Int32" /> </FunctionImport> <FunctionImport Name="ufnGetProductStandardCost" ReturnType="Collection(Decimal)"> <Parameter Name="ProductID" Mode="In" Type="Int32" /> <Parameter Name="OrderDate" Mode="In" Type="DateTime" /> </FunctionImport> </EntityContainer> </Schema> </edmx:ConceptualModels> */ // Build above <ConceptualModels> imperatively. EdmFunction modelFunction = EdmFunction.Create( storeFunction.Name, model.ConceptualModel.Container.Name, DataSpace.CSpace, // <edmx:ConceptualModels> new EdmFunctionPayload { IsFunctionImport = true, IsComposable = storeFunction.IsComposableAttribute, Parameters = model.GetModelParameters(methodInfo, storeFunction), ReturnParameters = model.GetModelReturnParameters(methodInfo, functionAttribute), EntitySets = model.GetModelEntitySets(methodInfo, functionAttribute) }, null); model.ConceptualModel.Container.AddFunctionImport(modelFunction); /* <!-- C-S mapping content --> <edmx:Mappings> <Mapping Space="C-S" xmlns="http://schemas.microsoft.com/ado/2009/11/mapping/cs"> <EntityContainerMapping StorageEntityContainer="CodeFirstDatabase" CdmEntityContainer="AdventureWorks"> <FunctionImportMapping FunctionImportName="ufnGetContactInformation" FunctionName="AdventureWorks.ufnGetContactInformation"> <ResultMapping> <ComplexTypeMapping TypeName="AdventureWorks.ContactInformation"> <ScalarProperty Name="PersonID" ColumnName="PersonID" /> <ScalarProperty Name="FirstName" ColumnName="FirstName" /> <ScalarProperty Name="LastName" ColumnName="LastName" /> <ScalarProperty Name="JobTitle" ColumnName="JobTitle" /> <ScalarProperty Name="BusinessEntityType" ColumnName="BusinessEntityType" /> </ComplexTypeMapping> </ResultMapping> </FunctionImportMapping> <FunctionImportMapping FunctionImportName="uspGetCategoryAndSubCategory" FunctionName="AdventureWorks.uspGetCategoryAndSubCategory"> <ResultMapping> <ComplexTypeMapping TypeName="AdventureWorks.CategoryAndSubCategory"> <ScalarProperty Name="ProductCategoryID" ColumnName="ProductCategoryID" /> <ScalarProperty Name="Name" ColumnName="Name" /> </ComplexTypeMapping> </ResultMapping> </FunctionImportMapping> <FunctionImportMapping FunctionImportName="uspGetManagerEmployees" FunctionName="AdventureWorks.uspGetManagerEmployees"> <ResultMapping> <ComplexTypeMapping TypeName="AdventureWorks.ManagerEmployee"> <ScalarProperty Name="RecursionLevel" ColumnName="RecursionLevel" /> <ScalarProperty Name="OrganizationNode" ColumnName="OrganizationNode" /> <ScalarProperty Name="ManagerFirstName" ColumnName="ManagerFirstName" /> <ScalarProperty Name="ManagerLastName" ColumnName="ManagerLastName" /> <ScalarProperty Name="BusinessEntityID" ColumnName="BusinessEntityID" /> <ScalarProperty Name="FirstName" ColumnName="FirstName" /> <ScalarProperty Name="LastName" ColumnName="LastName" /> </ComplexTypeMapping> </ResultMapping> </FunctionImportMapping> <FunctionImportMapping FunctionImportName="ufnGetProductStandardCost" FunctionName="AdventureWorks.ufnGetProductStandardCost" /> </EntityContainerMapping> </Mapping> </edmx:Mappings> */ // Build above <Mappings> imperatively. FunctionImportMapping mapping; if (modelFunction.IsComposableAttribute) { mapping = new FunctionImportMappingComposable( modelFunction, storeFunction, new FunctionImportResultMapping(), model.ConceptualToStoreMapping); } else { mapping = new FunctionImportMappingNonComposable( modelFunction, storeFunction, Enumerable.Empty<FunctionImportResultMapping>(), model.ConceptualToStoreMapping); } model.ConceptualToStoreMapping.AddFunctionImportMapping(mapping); }
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()); }
public void WriteFunctionImportMappingElement_does_not_write_result_mapping_for_non_composable_functions_mapped_implicitly() { var typeUsage = TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32)); var complexTypeProperty1 = new EdmProperty("CTProperty1", typeUsage); var complexTypeProperty2 = new EdmProperty("CTProperty2", typeUsage); var complexType = new ComplexType("CT", "Ns", DataSpace.CSpace); complexType.AddMember(complexTypeProperty1); complexType.AddMember(complexTypeProperty2); var functionImport = new EdmFunction( "f_c", "Ns", DataSpace.CSpace, new EdmFunctionPayload { IsComposable = false, IsFunctionImport = true, ReturnParameters = new[] { new FunctionParameter( "ReturnValue", TypeUsage.CreateDefaultTypeUsage(complexType.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 functionImportMapping = new FunctionImportMappingNonComposable( functionImport, storeFunction, new FunctionImportResultMapping[0], new EntityContainerMapping(new EntityContainer("C", DataSpace.SSpace))); var fixture = new Fixture(); fixture.Writer.WriteFunctionImportMappingElement(functionImportMapping); Assert.Equal( @"<FunctionImportMapping FunctionName=""Ns.Store.f_s"" FunctionImportName=""f_c"" />", fixture.ToString()); }
internal FunctionColumnMapGenerator( FunctionImportMappingNonComposable mapping, int resultSetIndex, EntitySet entitySet, StructuralType baseStructuralType, ColumnMapFactory columnMapFactory) { _mapping = mapping; _entitySet = entitySet; _baseStructuralType = baseStructuralType; _resultSetIndex = resultSetIndex; _columnMapFactory = columnMapFactory; }
/// <summary> /// Determines the store type for a function import. /// </summary> private TypeUsage DetermineStoreResultType( FunctionImportMappingNonComposable mapping, int resultSetIndex, out IColumnMapGenerator columnMapGenerator) { // Determine column maps and infer result types for the mapped function. There are four varieties: // Collection(Entity) // Collection(PrimitiveType) // Collection(ComplexType) // No result type TypeUsage storeResultType; { StructuralType baseStructuralType; var functionImport = mapping.FunctionImport; // Collection(Entity) or Collection(ComplexType) if (MetadataHelper.TryGetFunctionImportReturnType(functionImport, resultSetIndex, out baseStructuralType)) { ValidateEdmResultType(baseStructuralType, functionImport); //Note: Defensive check for historic reasons, we expect functionImport.EntitySets.Count > resultSetIndex var entitySet = functionImport.EntitySets.Count > resultSetIndex ? functionImport.EntitySets[resultSetIndex] : null; columnMapGenerator = new FunctionColumnMapGenerator( mapping, resultSetIndex, entitySet, baseStructuralType, _columnMapFactory); // We don't actually know the return type for the stored procedure, but we can infer // one based on the mapping (i.e.: a column for every property of the mapped types // and for all discriminator columns) storeResultType = mapping.GetExpectedTargetResultType(resultSetIndex); } // Collection(PrimitiveType) else { var returnParameter = MetadataHelper.GetReturnParameter(functionImport, resultSetIndex); if (returnParameter != null && returnParameter.TypeUsage != null) { // Get metadata description of the return type storeResultType = returnParameter.TypeUsage; Debug.Assert( storeResultType.EdmType.BuiltInTypeKind == BuiltInTypeKind.CollectionType, "FunctionImport currently supports only collection result type"); var elementType = ((CollectionType)storeResultType.EdmType).TypeUsage; Debug.Assert( Helper.IsScalarType(elementType.EdmType), "FunctionImport supports only Collection(Entity), Collection(Enum) and Collection(Primitive)"); // Build collection column map where the first column of the store result is assumed // to contain the primitive type values. var scalarColumnMap = new ScalarColumnMap(elementType, string.Empty, 0, 0); var collectionColumnMap = new SimpleCollectionColumnMap( storeResultType, string.Empty, scalarColumnMap, null, null); columnMapGenerator = new ConstantColumnMapGenerator(collectionColumnMap, 1); } // No result type else { storeResultType = null; columnMapGenerator = new ConstantColumnMapGenerator(null, 0); } } } return storeResultType; }
private static ScalarColumnMap[] CreateDiscriminatorColumnMaps( DbDataReader storeDataReader, FunctionImportMappingNonComposable mapping, int resultIndex) { // choose an arbitrary type for discriminator columns -- the type is not // actually statically known EdmType discriminatorType = MetadataItem.EdmProviderManifest.GetPrimitiveType(PrimitiveTypeKind.String); var discriminatorTypeUsage = TypeUsage.Create(discriminatorType); var discriminatorColumnNames = mapping.GetDiscriminatorColumns(resultIndex); var discriminatorColumns = new ScalarColumnMap[discriminatorColumnNames.Count]; for (var i = 0; i < discriminatorColumns.Length; i++) { var columnName = discriminatorColumnNames[i]; var columnMap = new ScalarColumnMap( discriminatorTypeUsage, columnName, 0, GetDiscriminatorOrdinalFromReader(storeDataReader, columnName, mapping.FunctionImport)); discriminatorColumns[i] = columnMap; } return discriminatorColumns; }
public void WriteFunctionImportMappingElement(FunctionImportMappingNonComposable functionImportMapping) { DebugCheck.NotNull(functionImportMapping); WriteFunctionImportMappingStartElement(functionImportMapping); foreach (var resultMapping in functionImportMapping.ResultMappings) { WriteFunctionImportResultMappingElement(resultMapping); } WriteFunctionImportEndElement(); }
public void Can_create_non_composable_function_with_multiple_results() { 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 complexType = ComplexType.Create( "RT1", "N", DataSpace.CSpace, new[] { EdmProperty.Create("P1", cTypeUsageInt), EdmProperty.Create("P2", cTypeUsageString) }, null); var entityType = EntityType.Create( "RT2", "N", DataSpace.CSpace, new[] { "P3" }, new[] { EdmProperty.Create("P3", cTypeUsageInt), EdmProperty.Create("P4", cTypeUsageString), }, null); var rowType1 = RowType.Create( new[] { EdmProperty.Create("C1", sTypeUsageInt), EdmProperty.Create("C2", sTypeUsageString) }, null); var rowType2 = RowType.Create( new[] { EdmProperty.Create("C3", sTypeUsageInt), EdmProperty.Create("C4", sTypeUsageString) }, null); var functionImport = EdmFunction.Create( "F", "N", DataSpace.CSpace, new EdmFunctionPayload { IsComposable = false, ReturnParameters = new[] { FunctionParameter.Create("R1", complexType.GetCollectionType(), ParameterMode.ReturnValue), FunctionParameter.Create("R2", entityType.GetCollectionType(), ParameterMode.ReturnValue) }, EntitySets = new[] { new EntitySet(), new EntitySet() } }, null); var targetFunction = EdmFunction.Create( "SF", "N", DataSpace.SSpace, new EdmFunctionPayload { IsComposable = false, ReturnParameters = new[] { FunctionParameter.Create("R1", rowType1.GetCollectionType(), ParameterMode.ReturnValue), FunctionParameter.Create("R2", rowType2.GetCollectionType(), ParameterMode.ReturnValue) }, EntitySets = new [] { new EntitySet(), new EntitySet() } }, null); var resultMappings = new List<FunctionImportResultMapping> { new FunctionImportResultMapping(), new FunctionImportResultMapping() }; resultMappings[0].AddTypeMapping(new FunctionImportComplexTypeMapping( complexType, new Collection<FunctionImportReturnTypePropertyMapping>() { new FunctionImportReturnTypeScalarPropertyMapping("P1", "C1"), new FunctionImportReturnTypeScalarPropertyMapping("P2", "C2"), })); resultMappings[1].AddTypeMapping(new FunctionImportEntityTypeMapping( Enumerable.Empty<EntityType>(), new [] { entityType }, new Collection<FunctionImportReturnTypePropertyMapping>() { new FunctionImportReturnTypeScalarPropertyMapping("P3", "C3"), new FunctionImportReturnTypeScalarPropertyMapping("P4", "C4") }, Enumerable.Empty<FunctionImportEntityTypeMappingCondition>())); var functionImportMapping = new FunctionImportMappingNonComposable( functionImport, targetFunction, resultMappings, containerMapping); Assert.Equal(resultMappings.Count, functionImportMapping.ResultMappings.Count); functionImportMapping.ResultMappings.Each(m => Assert.False(m.IsReadOnly)); functionImportMapping.SetReadOnly(); functionImportMapping.ResultMappings.Each(m => Assert.True(m.IsReadOnly)); }
public void Can_create_non_composable_function_with_multiple_results() { 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 complexType = ComplexType.Create( "RT1", "N", DataSpace.CSpace, new[] { EdmProperty.Create("P1", cTypeUsageInt), EdmProperty.Create("P2", cTypeUsageString) }, null); var entityType = EntityType.Create( "RT2", "N", DataSpace.CSpace, new[] { "P3" }, new[] { EdmProperty.Create("P3", cTypeUsageInt), EdmProperty.Create("P4", cTypeUsageString), }, null); var rowType1 = RowType.Create( new[] { EdmProperty.Create("C1", sTypeUsageInt), EdmProperty.Create("C2", sTypeUsageString) }, null); var rowType2 = RowType.Create( new[] { EdmProperty.Create("C3", sTypeUsageInt), EdmProperty.Create("C4", sTypeUsageString) }, null); var functionImport = EdmFunction.Create( "F", "N", DataSpace.CSpace, new EdmFunctionPayload { IsComposable = false, ReturnParameters = new[] { FunctionParameter.Create("R1", complexType.GetCollectionType(), ParameterMode.ReturnValue), FunctionParameter.Create("R2", entityType.GetCollectionType(), ParameterMode.ReturnValue) }, EntitySets = new[] { new EntitySet(), new EntitySet() } }, null); var targetFunction = EdmFunction.Create( "SF", "N", DataSpace.SSpace, new EdmFunctionPayload { IsComposable = false, ReturnParameters = new[] { FunctionParameter.Create("R1", rowType1.GetCollectionType(), ParameterMode.ReturnValue), FunctionParameter.Create("R2", rowType2.GetCollectionType(), ParameterMode.ReturnValue) }, EntitySets = new [] { new EntitySet(), new EntitySet() } }, null); var resultMappings = new List <FunctionImportResultMapping> { new FunctionImportResultMapping(), new FunctionImportResultMapping() }; resultMappings[0].AddTypeMapping(new FunctionImportComplexTypeMapping( complexType, new Collection <FunctionImportReturnTypePropertyMapping>() { new FunctionImportReturnTypeScalarPropertyMapping("P1", "C1"), new FunctionImportReturnTypeScalarPropertyMapping("P2", "C2"), })); resultMappings[1].AddTypeMapping(new FunctionImportEntityTypeMapping( Enumerable.Empty <EntityType>(), new [] { entityType }, new Collection <FunctionImportReturnTypePropertyMapping>() { new FunctionImportReturnTypeScalarPropertyMapping("P3", "C3"), new FunctionImportReturnTypeScalarPropertyMapping("P4", "C4") }, Enumerable.Empty <FunctionImportEntityTypeMappingCondition>())); var functionImportMapping = new FunctionImportMappingNonComposable( functionImport, targetFunction, resultMappings, containerMapping); Assert.Equal(resultMappings.Count, functionImportMapping.ResultMappings.Count); functionImportMapping.ResultMappings.Each(m => Assert.False(m.IsReadOnly)); functionImportMapping.SetReadOnly(); functionImportMapping.ResultMappings.Each(m => Assert.True(m.IsReadOnly)); }