private static DbExpression GeneratePropertyMappingView( PropertyMapping mapping, DbExpression row) { ScalarPropertyMapping scalarPropertyMapping = (ScalarPropertyMapping)mapping; return(FunctionImportMappingComposable.GenerateScalarPropertyMappingView(scalarPropertyMapping.Property, scalarPropertyMapping.Column, row)); }
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); }
private static DbExpression GenerateScalarPropertyMappingView( EdmProperty edmProperty, EdmProperty columnProperty, DbExpression row) { DbExpression columnRef = FunctionImportMappingComposable.GenerateColumnRef(row, columnProperty); if (!TypeSemantics.IsEqual(columnRef.ResultType, edmProperty.TypeUsage)) { columnRef = (DbExpression)columnRef.CastTo(edmProperty.TypeUsage); } return(columnRef); }
private static DbExpression GenerateStructuralTypeMappingView( StructuralType structuralType, List <PropertyMapping> propertyMappings, DbExpression row) { List <DbExpression> dbExpressionList = new List <DbExpression>(TypeHelpers.GetAllStructuralMembers((EdmType)structuralType).Count); for (int index = 0; index < propertyMappings.Count; ++index) { PropertyMapping propertyMapping = propertyMappings[index]; dbExpressionList.Add(FunctionImportMappingComposable.GeneratePropertyMappingView(propertyMapping, row)); } return((DbExpression)TypeUsage.Create((EdmType)structuralType).New((IEnumerable <DbExpression>)dbExpressionList)); }
private static DbExpression GeneratePredicate( ConditionPropertyMapping condition, DbExpression row) { DbExpression columnRef = FunctionImportMappingComposable.GenerateColumnRef(row, condition.Column); if (!condition.IsNull.HasValue) { return((DbExpression)columnRef.Equal((DbExpression)columnRef.ResultType.Constant(condition.Value))); } if (!condition.IsNull.Value) { return((DbExpression)columnRef.IsNull().Not()); } return((DbExpression)columnRef.IsNull()); }
public void Can_add_and_get_function_import_mapping() { var typeUsage = TypeUsage.CreateDefaultTypeUsage( PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32).GetCollectionType()); var entityContainerMapping = new EntityContainerMapping(new EntityContainer("C", DataSpace.CSpace)); var composableFunctionMapping = new FunctionImportMappingComposable( new EdmFunction( "f", "model", DataSpace.CSpace, new EdmFunctionPayload() { IsComposable = true, ReturnParameters = new[] { new FunctionParameter( "ReturnType", typeUsage, ParameterMode.ReturnValue), } }), new EdmFunction( "f", "store", DataSpace.SSpace, new EdmFunctionPayload() { IsComposable = true, ReturnParameters = new[] { new FunctionParameter( "ReturnType", typeUsage, ParameterMode.ReturnValue), } }), null); Assert.Empty(entityContainerMapping.FunctionImportMappings); entityContainerMapping.AddFunctionImportMapping(composableFunctionMapping); Assert.Same(composableFunctionMapping, entityContainerMapping.FunctionImportMappings.Single()); }
internal bool TryCreateFunctionImportMappingComposableWithScalarResult( EdmFunction functionImport, EdmFunction cTypeTargetFunction, EdmFunction sTypeTargetFunction, EdmType scalarResultType, RowType cTypeTvfElementType, IXmlLineInfo lineInfo, out FunctionImportMappingComposable mapping) { mapping = null; // Make sure that TVF returns exactly one column if (cTypeTvfElementType.Properties.Count > 1) { AddToSchemaErrors( Strings.Mapping_FunctionImport_ScalarMappingToMulticolumnTVF(functionImport.Identity, sTypeTargetFunction.Identity), MappingErrorCode.MappingFunctionImportScalarMappingToMulticolumnTVF, m_sourceLocation, lineInfo, m_parsingErrors); return(false); } // Make sure that scalarResultType agrees with the column type. if ( !ValidateFunctionImportMappingResultTypeCompatibility( TypeUsage.Create(scalarResultType), cTypeTvfElementType.Properties[0].TypeUsage)) { AddToSchemaErrors( Strings.Mapping_FunctionImport_ScalarMappingTypeMismatch( functionImport.ReturnParameter.TypeUsage.EdmType.FullName, functionImport.Identity, sTypeTargetFunction.ReturnParameter.TypeUsage.EdmType.FullName, sTypeTargetFunction.Identity), MappingErrorCode.MappingFunctionImportScalarMappingTypeMismatch, m_sourceLocation, lineInfo, m_parsingErrors); return(false); } mapping = new FunctionImportMappingComposable( functionImport, cTypeTargetFunction, null, null, _entityContainerMapping); return(true); }
public void Can_get_structural_type_mappings() { var complexType = new ComplexType("CT", "ns", DataSpace.CSpace); var functionImport = new EdmFunction( "f", "entityModel", DataSpace.CSpace, new EdmFunctionPayload { IsComposable = true, ReturnParameters = new[] { new FunctionParameter( "ReturnType", TypeUsage.CreateDefaultTypeUsage(complexType.GetCollectionType()), ParameterMode.ReturnValue) } }); var structuralTypeMapping = new List <Tuple <StructuralType, List <ConditionPropertyMapping>, List <PropertyMapping> > > { new Tuple <StructuralType, List <ConditionPropertyMapping>, List <PropertyMapping> >( complexType, null, null) }; var functionImportMapping = new FunctionImportMappingComposable( functionImport, new EdmFunction( "f", "store", DataSpace.CSpace, new EdmFunctionPayload { IsComposable = true }), structuralTypeMapping); Assert.Equal(structuralTypeMapping, functionImportMapping.StructuralTypeMappings); }
private DbExpression GenerateStructuralTypeResultMappingView( DbExpression storeFunctionInvoke, out DiscriminatorMap discriminatorMap) { discriminatorMap = (DiscriminatorMap)null; DbExpression dbExpression = storeFunctionInvoke; DbExpression queryView; if (this.m_structuralTypeMappings.Count == 1) { Tuple <StructuralType, List <ConditionPropertyMapping>, List <PropertyMapping> > structuralTypeMapping = this.m_structuralTypeMappings[0]; StructuralType structuralType = structuralTypeMapping.Item1; List <ConditionPropertyMapping> conditions = structuralTypeMapping.Item2; List <PropertyMapping> propertyMappings = structuralTypeMapping.Item3; if (conditions.Count > 0) { dbExpression = (DbExpression)dbExpression.Where((Func <DbExpression, DbExpression>)(row => FunctionImportMappingComposable.GenerateStructuralTypeConditionsPredicate(conditions, row))); } DbExpressionBinding input = dbExpression.BindAs("row"); DbExpression structuralTypeMappingView = FunctionImportMappingComposable.GenerateStructuralTypeMappingView(structuralType, propertyMappings, (DbExpression)input.Variable); queryView = (DbExpression)input.Project(structuralTypeMappingView); } else { DbExpressionBinding binding = dbExpression.BindAs("row"); List <DbExpression> list = this.m_structuralTypeMappings.Select <Tuple <StructuralType, List <ConditionPropertyMapping>, List <PropertyMapping> >, DbExpression>((Func <Tuple <StructuralType, List <ConditionPropertyMapping>, List <PropertyMapping> >, DbExpression>)(m => FunctionImportMappingComposable.GenerateStructuralTypeConditionsPredicate(m.Item2, (DbExpression)binding.Variable))).ToList <DbExpression>(); binding = binding.Filter(Helpers.BuildBalancedTreeInPlace <DbExpression>((IList <DbExpression>)list.ToArray(), (Func <DbExpression, DbExpression, DbExpression>)((prev, next) => (DbExpression)prev.Or(next)))).BindAs("row"); List <DbExpression> source = new List <DbExpression>(this.m_structuralTypeMappings.Count); foreach (Tuple <StructuralType, List <ConditionPropertyMapping>, List <PropertyMapping> > structuralTypeMapping in this.m_structuralTypeMappings) { StructuralType structuralType = structuralTypeMapping.Item1; List <PropertyMapping> propertyMappings = structuralTypeMapping.Item3; source.Add(FunctionImportMappingComposable.GenerateStructuralTypeMappingView(structuralType, propertyMappings, (DbExpression)binding.Variable)); } DbExpression projection = (DbExpression)DbExpressionBuilder.Case(list.Take <DbExpression>(this.m_structuralTypeMappings.Count - 1), source.Take <DbExpression>(this.m_structuralTypeMappings.Count - 1), source[this.m_structuralTypeMappings.Count - 1]); queryView = (DbExpression)binding.Project(projection); DiscriminatorMap.TryCreateDiscriminatorMap(this.FunctionImport.EntitySet, queryView, out discriminatorMap); } return(queryView); }
internal bool TryCreateFunctionImportMappingComposableWithScalarResult( EdmFunction functionImport, EdmFunction cTypeTargetFunction, EdmFunction sTypeTargetFunction, EdmType scalarResultType, RowType cTypeTvfElementType, IXmlLineInfo lineInfo, out FunctionImportMappingComposable mapping) { mapping = (FunctionImportMappingComposable)null; if (cTypeTvfElementType.Properties.Count > 1) { FunctionImportMappingComposableHelper.AddToSchemaErrors(Strings.Mapping_FunctionImport_ScalarMappingToMulticolumnTVF((object)functionImport.Identity, (object)sTypeTargetFunction.Identity), MappingErrorCode.MappingFunctionImportScalarMappingToMulticolumnTVF, this.m_sourceLocation, lineInfo, (IList <EdmSchemaError>) this.m_parsingErrors); return(false); } if (!FunctionImportMappingComposableHelper.ValidateFunctionImportMappingResultTypeCompatibility(TypeUsage.Create(scalarResultType), cTypeTvfElementType.Properties[0].TypeUsage)) { FunctionImportMappingComposableHelper.AddToSchemaErrors(Strings.Mapping_FunctionImport_ScalarMappingTypeMismatch((object)functionImport.ReturnParameter.TypeUsage.EdmType.FullName, (object)functionImport.Identity, (object)sTypeTargetFunction.ReturnParameter.TypeUsage.EdmType.FullName, (object)sTypeTargetFunction.Identity), MappingErrorCode.MappingFunctionImportScalarMappingTypeMismatch, this.m_sourceLocation, lineInfo, (IList <EdmSchemaError>) this.m_parsingErrors); return(false); } mapping = new FunctionImportMappingComposable(functionImport, cTypeTargetFunction, (List <Tuple <StructuralType, List <ConditionPropertyMapping>, List <PropertyMapping> > >)null, (EdmProperty[])null, this._entityContainerMapping); return(true); }
public void WriteEntityContainerMappingElement_should_write_function_import_elements_mapped_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 = true, IsFunctionImport = true, ReturnParameters = new[] { new FunctionParameter( "ReturnValue", TypeUsage.CreateDefaultTypeUsage(entityType.GetCollectionType()), ParameterMode.ReturnValue) }, Parameters = new[] { new FunctionParameter("param", typeUsage, ParameterMode.Out) } }); 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 { ReturnParameters = new[] { new FunctionParameter( "Return", TypeUsage.CreateDefaultTypeUsage(rowType), ParameterMode.ReturnValue) }, Parameters = new[] { new FunctionParameter("param", typeUsage, ParameterMode.Out) } }); var structuralTypeMapping = new Tuple<StructuralType, List<ConditionPropertyMapping>, List<PropertyMapping>>( entityType, new List<ConditionPropertyMapping>(), new List<PropertyMapping>()); structuralTypeMapping.Item2.Add(new ConditionPropertyMapping(rowTypeProperty1, null, false)); structuralTypeMapping.Item3.Add(new ScalarPropertyMapping(entityTypeProperty1, rowTypeProperty1)); structuralTypeMapping.Item3.Add(new ScalarPropertyMapping(entityTypeProperty2, rowTypeProperty2)); var functionImportMapping = new FunctionImportMappingComposable( functionImport, storeFunction, new List<Tuple<StructuralType, List<ConditionPropertyMapping>, List<PropertyMapping>>> { structuralTypeMapping }); var containerMapping = new EntityContainerMapping(new EntityContainer("C", DataSpace.SSpace)); containerMapping.AddFunctionImportMapping(functionImportMapping); var fixture = new Fixture(); fixture.Writer.WriteEntityContainerMappingElement(containerMapping); Assert.Equal( @"<EntityContainerMapping StorageEntityContainer="""" CdmEntityContainer=""C""> <FunctionImportMapping FunctionName=""Ns.Store.f_s"" FunctionImportName=""f_c""> <ResultMapping> <EntityTypeMapping TypeName=""Ns.ET""> <Condition IsNull=""false"" ColumnName=""RTProperty1"" /> <ScalarProperty Name=""ETProperty1"" ColumnName=""RTProperty1"" /> <ScalarProperty Name=""ETProperty2"" ColumnName=""RTProperty2"" /> </EntityTypeMapping> </ResultMapping> </FunctionImportMapping> </EntityContainerMapping>", fixture.ToString()); }
internal bool TryCreateFunctionImportMappingComposableWithStructuralResult( EdmFunction functionImport, EdmFunction cTypeTargetFunction, List <FunctionImportStructuralTypeMapping> typeMappings, RowType cTypeTvfElementType, RowType sTypeTvfElementType, IXmlLineInfo lineInfo, out FunctionImportMappingComposable mapping) { mapping = null; // If it is an implicit structural type mapping, add a type mapping fragment for the return type of the function import, // unless it is an abstract type. if (typeMappings.Count == 0) { StructuralType resultType; if (MetadataHelper.TryGetFunctionImportReturnType(functionImport, 0, out resultType)) { if (resultType.Abstract) { AddToSchemaErrorWithMemberAndStructure( Strings.Mapping_FunctionImport_ImplicitMappingForAbstractReturnType, resultType.FullName, functionImport.Identity, MappingErrorCode.MappingOfAbstractType, m_sourceLocation, lineInfo, m_parsingErrors); return(false); } if (resultType.BuiltInTypeKind == BuiltInTypeKind.EntityType) { typeMappings.Add( new FunctionImportEntityTypeMapping( Enumerable.Empty <EntityType>(), new[] { (EntityType)resultType }, Enumerable.Empty <FunctionImportEntityTypeMappingCondition>(), new Collection <FunctionImportReturnTypePropertyMapping>(), new LineInfo(lineInfo))); } else { Debug.Assert( resultType.BuiltInTypeKind == BuiltInTypeKind.ComplexType, "resultType.BuiltInTypeKind == BuiltInTypeKind.ComplexType"); typeMappings.Add( new FunctionImportComplexTypeMapping( (ComplexType)resultType, new Collection <FunctionImportReturnTypePropertyMapping>(), new LineInfo(lineInfo))); } } } // 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 provide an empty EdmItemCollection which // will allow inferring implicit result mapping var edmItemCollection = _entityContainerMapping.StorageMappingItemCollection != null ? _entityContainerMapping.StorageMappingItemCollection.EdmItemCollection : new EdmItemCollection(new EdmModel(DataSpace.CSpace)); // Validate and convert FunctionImportEntityTypeMapping elements into structure suitable for composable function import mapping. var functionImportKB = new FunctionImportStructuralTypeMappingKB(typeMappings, edmItemCollection); var structuralTypeMappings = new List <Tuple <StructuralType, List <ConditionPropertyMapping>, List <PropertyMapping> > >(); EdmProperty[] targetFunctionKeys = null; if (functionImportKB.MappedEntityTypes.Count > 0) { // Validate TPH ambiguity. if (!functionImportKB.ValidateTypeConditions(/*validateAmbiguity: */ true, m_parsingErrors, m_sourceLocation)) { return(false); } // For each mapped entity type, prepare list of conditions and list of property mappings. for (var i = 0; i < functionImportKB.MappedEntityTypes.Count; ++i) { List <ConditionPropertyMapping> typeConditions; List <PropertyMapping> propertyMappings; if (TryConvertToEntityTypeConditionsAndPropertyMappings( functionImport, functionImportKB, i, cTypeTvfElementType, sTypeTvfElementType, lineInfo, out typeConditions, out propertyMappings)) { structuralTypeMappings.Add( Tuple.Create((StructuralType)functionImportKB.MappedEntityTypes[i], typeConditions, propertyMappings)); } } if (structuralTypeMappings.Count < functionImportKB.MappedEntityTypes.Count) { // Some of the entity types produced errors during conversion, exit. return(false); } // Infer target function keys based on the c-space entity types. if (!TryInferTVFKeys(structuralTypeMappings, out targetFunctionKeys)) { AddToSchemaErrorsWithMemberInfo( Strings.Mapping_FunctionImport_CannotInferTargetFunctionKeys, functionImport.Identity, MappingErrorCode.MappingFunctionImportCannotInferTargetFunctionKeys, m_sourceLocation, lineInfo, m_parsingErrors); return(false); } } else { ComplexType resultComplexType; if (MetadataHelper.TryGetFunctionImportReturnType(functionImport, 0, out resultComplexType)) { // Gather and validate complex type property mappings. List <PropertyMapping> propertyMappings; if ( !TryConvertToPropertyMappings( resultComplexType, cTypeTvfElementType, sTypeTvfElementType, functionImport, functionImportKB, lineInfo, out propertyMappings)) { return(false); } structuralTypeMappings.Add( Tuple.Create((StructuralType)resultComplexType, new List <ConditionPropertyMapping>(), propertyMappings)); } else { Debug.Fail("Function import return type is expected to be a collection of complex type."); } } mapping = new FunctionImportMappingComposable( functionImport, cTypeTargetFunction, structuralTypeMappings, targetFunctionKeys, _entityContainerMapping); return(true); }
public void WriteFunctionImportMappingElement(FunctionImportMappingComposable functionImportMapping) { DebugCheck.NotNull(functionImportMapping); _xmlWriter.WriteStartElement(StorageMslConstructs.FunctionImportMappingElement); _xmlWriter.WriteAttributeString( StorageMslConstructs.FunctionImportMappingFunctionNameAttribute, functionImportMapping.TargetFunction.FullName); _xmlWriter.WriteAttributeString( StorageMslConstructs.FunctionImportMappingFunctionImportNameAttribute, functionImportMapping.FunctionImport.Name); _xmlWriter.WriteStartElement(StorageMslConstructs.FunctionImportMappingResultMapping); Debug.Assert( functionImportMapping.StructuralTypeMappings.Count == 1, "multiple result sets not supported."); Debug.Assert( functionImportMapping.StructuralTypeMappings.First().Item1.BuiltInTypeKind == BuiltInTypeKind.ComplexType, "mapping to entity sets not supported."); var structuralMapping = functionImportMapping.StructuralTypeMappings.Single(); _xmlWriter.WriteStartElement(StorageMslConstructs.ComplexTypeMappingElement); _xmlWriter.WriteAttributeString(StorageMslConstructs.ComplexTypeMappingTypeNameAttribute, structuralMapping.Item1.FullName); foreach (StorageScalarPropertyMapping propertyMapping in structuralMapping.Item3) { WritePropertyMapping(propertyMapping); } _xmlWriter.WriteEndElement(); _xmlWriter.WriteEndElement(); _xmlWriter.WriteEndElement(); }
public void WriteFunctionImportMappingElement(FunctionImportMappingComposable functionImportMapping) { DebugCheck.NotNull(functionImportMapping); WriteFunctionImportMappingStartElement(functionImportMapping); // no mapping written when mapping to a scalar if (functionImportMapping.StructuralTypeMappings != null) { _xmlWriter.WriteStartElement(MslConstructs.FunctionImportMappingResultMapping); Debug.Assert( functionImportMapping.StructuralTypeMappings.Count == 1, "multiple result sets not supported."); var structuralMapping = functionImportMapping.StructuralTypeMappings.Single(); if (structuralMapping.Item1.BuiltInTypeKind == BuiltInTypeKind.ComplexType) { _xmlWriter.WriteStartElement(MslConstructs.ComplexTypeMappingElement); _xmlWriter.WriteAttributeString(MslConstructs.ComplexTypeMappingTypeNameAttribute, structuralMapping.Item1.FullName); } else { Debug.Assert(structuralMapping.Item1.BuiltInTypeKind == BuiltInTypeKind.EntityType, "Unexpected return type"); _xmlWriter.WriteStartElement(MslConstructs.EntityTypeMappingElement); _xmlWriter.WriteAttributeString(MslConstructs.EntityTypeMappingTypeNameAttribute, structuralMapping.Item1.FullName); foreach (var conditionMapping in structuralMapping.Item2) { WriteConditionElement(conditionMapping); } } foreach (var propertyMapping in structuralMapping.Item3) { WritePropertyMapping(propertyMapping); } _xmlWriter.WriteEndElement(); _xmlWriter.WriteEndElement(); } WriteFunctionImportEndElement(); }
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 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 Can_get_structural_type_mappings() { var complexType = new ComplexType("CT", "ns", DataSpace.CSpace); var functionImport = new EdmFunction( "f", "entityModel", DataSpace.CSpace, new EdmFunctionPayload { IsComposable = true, ReturnParameters = new[] { new FunctionParameter( "ReturnType", TypeUsage.CreateDefaultTypeUsage(complexType.GetCollectionType()), ParameterMode.ReturnValue) } }); var structuralTypeMapping = new List<Tuple<StructuralType, List<StorageConditionPropertyMapping>, List<StoragePropertyMapping>>> { new Tuple<StructuralType, List<StorageConditionPropertyMapping>, List<StoragePropertyMapping>>( complexType, null, null) }; var functionImportMapping = new FunctionImportMappingComposable( functionImport, new EdmFunction( "f", "store", DataSpace.CSpace, new EdmFunctionPayload { IsComposable = true }), structuralTypeMapping); Assert.Equal(structuralTypeMapping, functionImportMapping.StructuralTypeMappings); }
internal bool TryCreateFunctionImportMappingComposableWithStructuralResult( EdmFunction functionImport, EdmFunction cTypeTargetFunction, List <FunctionImportStructuralTypeMapping> typeMappings, RowType cTypeTvfElementType, RowType sTypeTvfElementType, IXmlLineInfo lineInfo, out FunctionImportMappingComposable mapping) { mapping = (FunctionImportMappingComposable)null; StructuralType returnType1; if (typeMappings.Count == 0 && MetadataHelper.TryGetFunctionImportReturnType <StructuralType>(functionImport, 0, out returnType1)) { if (returnType1.Abstract) { FunctionImportMappingComposableHelper.AddToSchemaErrorWithMemberAndStructure(new Func <object, object, string>(Strings.Mapping_FunctionImport_ImplicitMappingForAbstractReturnType), returnType1.FullName, functionImport.Identity, MappingErrorCode.MappingOfAbstractType, this.m_sourceLocation, lineInfo, (IList <EdmSchemaError>) this.m_parsingErrors); return(false); } if (returnType1.BuiltInTypeKind == BuiltInTypeKind.EntityType) { typeMappings.Add((FunctionImportStructuralTypeMapping) new FunctionImportEntityTypeMapping(Enumerable.Empty <System.Data.Entity.Core.Metadata.Edm.EntityType>(), (IEnumerable <System.Data.Entity.Core.Metadata.Edm.EntityType>) new System.Data.Entity.Core.Metadata.Edm.EntityType[1] { (System.Data.Entity.Core.Metadata.Edm.EntityType)returnType1 }, Enumerable.Empty <FunctionImportEntityTypeMappingCondition>(), new Collection <FunctionImportReturnTypePropertyMapping>(), new LineInfo(lineInfo))); } else { typeMappings.Add((FunctionImportStructuralTypeMapping) new FunctionImportComplexTypeMapping((ComplexType)returnType1, new Collection <FunctionImportReturnTypePropertyMapping>(), new LineInfo(lineInfo))); } } EdmItemCollection edmItemCollection = this._entityContainerMapping.StorageMappingItemCollection != null ? this._entityContainerMapping.StorageMappingItemCollection.EdmItemCollection : new EdmItemCollection(new EdmModel(DataSpace.CSpace, 3.0)); FunctionImportStructuralTypeMappingKB functionImportKB = new FunctionImportStructuralTypeMappingKB((IEnumerable <FunctionImportStructuralTypeMapping>)typeMappings, (ItemCollection)edmItemCollection); List <Tuple <StructuralType, List <ConditionPropertyMapping>, List <PropertyMapping> > > structuralTypeMappings = new List <Tuple <StructuralType, List <ConditionPropertyMapping>, List <PropertyMapping> > >(); EdmProperty[] keys = (EdmProperty[])null; if (functionImportKB.MappedEntityTypes.Count > 0) { if (!functionImportKB.ValidateTypeConditions(true, (IList <EdmSchemaError>) this.m_parsingErrors, this.m_sourceLocation)) { return(false); } for (int typeID = 0; typeID < functionImportKB.MappedEntityTypes.Count; ++typeID) { List <ConditionPropertyMapping> typeConditions; List <PropertyMapping> propertyMappings; if (this.TryConvertToEntityTypeConditionsAndPropertyMappings(functionImport, functionImportKB, typeID, cTypeTvfElementType, sTypeTvfElementType, lineInfo, out typeConditions, out propertyMappings)) { structuralTypeMappings.Add(Tuple.Create <StructuralType, List <ConditionPropertyMapping>, List <PropertyMapping> >((StructuralType)functionImportKB.MappedEntityTypes[typeID], typeConditions, propertyMappings)); } } if (structuralTypeMappings.Count < functionImportKB.MappedEntityTypes.Count) { return(false); } if (!FunctionImportMappingComposableHelper.TryInferTVFKeys(structuralTypeMappings, out keys)) { FunctionImportMappingComposableHelper.AddToSchemaErrorsWithMemberInfo(new Func <object, string>(Strings.Mapping_FunctionImport_CannotInferTargetFunctionKeys), functionImport.Identity, MappingErrorCode.MappingFunctionImportCannotInferTargetFunctionKeys, this.m_sourceLocation, lineInfo, (IList <EdmSchemaError>) this.m_parsingErrors); return(false); } } else { ComplexType returnType2; if (MetadataHelper.TryGetFunctionImportReturnType <ComplexType>(functionImport, 0, out returnType2)) { List <PropertyMapping> propertyMappings; if (!this.TryConvertToPropertyMappings((StructuralType)returnType2, cTypeTvfElementType, sTypeTvfElementType, functionImport, functionImportKB, lineInfo, out propertyMappings)) { return(false); } structuralTypeMappings.Add(Tuple.Create <StructuralType, List <ConditionPropertyMapping>, List <PropertyMapping> >((StructuralType)returnType2, new List <ConditionPropertyMapping>(), propertyMappings)); } } mapping = new FunctionImportMappingComposable(functionImport, cTypeTargetFunction, structuralTypeMappings, keys, this._entityContainerMapping); return(true); }
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 WriteFunctionImportMappingElement_does_not_write_result_mapping_when_result_mapped_to_primitive_type() { var typeUsage = TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32)); var functionImport = new EdmFunction( "f_c", "Ns", DataSpace.CSpace, new EdmFunctionPayload { IsComposable = true, IsFunctionImport = true, ReturnParameters = new[] { new FunctionParameter( "ReturnValue", TypeUsage.CreateDefaultTypeUsage(typeUsage.EdmType.GetCollectionType()), ParameterMode.ReturnValue) }, }); var rowTypeProperty = new EdmProperty("RTProperty1", ProviderRegistry.Sql2008_ProviderManifest.GetStoreType(typeUsage)); var rowType = new RowType(new[] { rowTypeProperty }); var storeFunction = new EdmFunction( "f_s", "Ns.Store", DataSpace.SSpace, new EdmFunctionPayload { ReturnParameters = new[] { new FunctionParameter( "Return", TypeUsage.CreateDefaultTypeUsage(rowType.GetCollectionType()), ParameterMode.ReturnValue) }, }); var functionImportMapping = new FunctionImportMappingComposable( functionImport, storeFunction, new FunctionImportResultMapping(), 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 bool TryCreateFunctionImportMappingComposableWithStructuralResult( EdmFunction functionImport, EdmFunction cTypeTargetFunction, List<FunctionImportStructuralTypeMapping> typeMappings, RowType cTypeTvfElementType, RowType sTypeTvfElementType, IXmlLineInfo lineInfo, out FunctionImportMappingComposable mapping) { mapping = null; // If it is an implicit structural type mapping, add a type mapping fragment for the return type of the function import, // unless it is an abstract type. if (typeMappings.Count == 0) { StructuralType resultType; if (MetadataHelper.TryGetFunctionImportReturnType(functionImport, 0, out resultType)) { if (resultType.Abstract) { AddToSchemaErrorWithMemberAndStructure( Strings.Mapping_FunctionImport_ImplicitMappingForAbstractReturnType, resultType.FullName, functionImport.Identity, MappingErrorCode.MappingOfAbstractType, m_sourceLocation, lineInfo, m_parsingErrors); return false; } if (resultType.BuiltInTypeKind == BuiltInTypeKind.EntityType) { typeMappings.Add( new FunctionImportEntityTypeMapping( Enumerable.Empty<EntityType>(), new[] { (EntityType)resultType }, Enumerable.Empty<FunctionImportEntityTypeMappingCondition>(), new Collection<FunctionImportReturnTypePropertyMapping>(), new LineInfo(lineInfo))); } else { Debug.Assert( resultType.BuiltInTypeKind == BuiltInTypeKind.ComplexType, "resultType.BuiltInTypeKind == BuiltInTypeKind.ComplexType"); typeMappings.Add( new FunctionImportComplexTypeMapping( (ComplexType)resultType, new Collection<FunctionImportReturnTypePropertyMapping>(), new LineInfo(lineInfo))); } } } // 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 provide an empty EdmItemCollection which // will allow inferring implicit result mapping var edmItemCollection = _entityContainerMapping.StorageMappingItemCollection != null ? _entityContainerMapping.StorageMappingItemCollection.EdmItemCollection : new EdmItemCollection(new EdmModel(DataSpace.CSpace)); // Validate and convert FunctionImportEntityTypeMapping elements into structure suitable for composable function import mapping. var functionImportKB = new FunctionImportStructuralTypeMappingKB(typeMappings, edmItemCollection); var structuralTypeMappings = new List<Tuple<StructuralType, List<ConditionPropertyMapping>, List<PropertyMapping>>>(); EdmProperty[] targetFunctionKeys = null; if (functionImportKB.MappedEntityTypes.Count > 0) { // Validate TPH ambiguity. if (!functionImportKB.ValidateTypeConditions( /*validateAmbiguity: */true, m_parsingErrors, m_sourceLocation)) { return false; } // For each mapped entity type, prepare list of conditions and list of property mappings. for (var i = 0; i < functionImportKB.MappedEntityTypes.Count; ++i) { List<ConditionPropertyMapping> typeConditions; List<PropertyMapping> propertyMappings; if (TryConvertToEntityTypeConditionsAndPropertyMappings( functionImport, functionImportKB, i, cTypeTvfElementType, sTypeTvfElementType, lineInfo, out typeConditions, out propertyMappings)) { structuralTypeMappings.Add( Tuple.Create((StructuralType)functionImportKB.MappedEntityTypes[i], typeConditions, propertyMappings)); } } if (structuralTypeMappings.Count < functionImportKB.MappedEntityTypes.Count) { // Some of the entity types produced errors during conversion, exit. return false; } // Infer target function keys based on the c-space entity types. if (!TryInferTVFKeys(structuralTypeMappings, out targetFunctionKeys)) { AddToSchemaErrorsWithMemberInfo( Strings.Mapping_FunctionImport_CannotInferTargetFunctionKeys, functionImport.Identity, MappingErrorCode.MappingFunctionImportCannotInferTargetFunctionKeys, m_sourceLocation, lineInfo, m_parsingErrors); return false; } } else { ComplexType resultComplexType; if (MetadataHelper.TryGetFunctionImportReturnType(functionImport, 0, out resultComplexType)) { // Gather and validate complex type property mappings. List<PropertyMapping> propertyMappings; if ( !TryConvertToPropertyMappings( resultComplexType, cTypeTvfElementType, sTypeTvfElementType, functionImport, functionImportKB, lineInfo, out propertyMappings)) { return false; } structuralTypeMappings.Add( Tuple.Create((StructuralType)resultComplexType, new List<ConditionPropertyMapping>(), propertyMappings)); } else { Debug.Fail("Function import return type is expected to be a collection of complex type."); } } mapping = new FunctionImportMappingComposable( functionImport, cTypeTargetFunction, structuralTypeMappings, targetFunctionKeys, _entityContainerMapping); return true; }
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 Can_add_and_get_function_import_mapping() { var typeUsage = TypeUsage.CreateDefaultTypeUsage( PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32).GetCollectionType()); var entityContainerMapping = new EntityContainerMapping(new EntityContainer("C", DataSpace.CSpace)); var composableFuntionMapping = new FunctionImportMappingComposable( new EdmFunction( "f", "model", DataSpace.CSpace, new EdmFunctionPayload() { IsComposable = true, ReturnParameters = new[] { new FunctionParameter( "ReturnType", typeUsage, ParameterMode.ReturnValue), } }), new EdmFunction( "f", "store", DataSpace.SSpace, new EdmFunctionPayload() { IsComposable = true, ReturnParameters = new[] { new FunctionParameter( "ReturnType", typeUsage, ParameterMode.ReturnValue), } }), null); Assert.Empty(entityContainerMapping.FunctionImportMappings); entityContainerMapping.AddFunctionImportMapping(composableFuntionMapping); Assert.Same(composableFuntionMapping, entityContainerMapping.FunctionImportMappings.Single()); }
internal bool TryCreateFunctionImportMappingComposableWithScalarResult( EdmFunction functionImport, EdmFunction cTypeTargetFunction, EdmFunction sTypeTargetFunction, EdmType scalarResultType, RowType cTypeTvfElementType, IXmlLineInfo lineInfo, out FunctionImportMappingComposable mapping) { mapping = null; // Make sure that TVF returns exactly one column if (cTypeTvfElementType.Properties.Count > 1) { AddToSchemaErrors( Strings.Mapping_FunctionImport_ScalarMappingToMulticolumnTVF(functionImport.Identity, sTypeTargetFunction.Identity), MappingErrorCode.MappingFunctionImportScalarMappingToMulticolumnTVF, m_sourceLocation, lineInfo, m_parsingErrors); return false; } // Make sure that scalarResultType agrees with the column type. if ( !ValidateFunctionImportMappingResultTypeCompatibility( TypeUsage.Create(scalarResultType), cTypeTvfElementType.Properties[0].TypeUsage)) { AddToSchemaErrors( Strings.Mapping_FunctionImport_ScalarMappingTypeMismatch( functionImport.ReturnParameter.TypeUsage.EdmType.FullName, functionImport.Identity, sTypeTargetFunction.ReturnParameter.TypeUsage.EdmType.FullName, sTypeTargetFunction.Identity), MappingErrorCode.MappingFunctionImportScalarMappingTypeMismatch, m_sourceLocation, lineInfo, m_parsingErrors); return false; } mapping = new FunctionImportMappingComposable( functionImport, cTypeTargetFunction, null, null, _entityContainerMapping); return true; }
private static DbExpression GenerateStructuralTypeConditionsPredicate( List <ConditionPropertyMapping> conditions, DbExpression row) { return(Helpers.BuildBalancedTreeInPlace <DbExpression>((IList <DbExpression>)conditions.Select <ConditionPropertyMapping, DbExpression>((Func <ConditionPropertyMapping, DbExpression>)(c => FunctionImportMappingComposable.GeneratePredicate(c, row))).ToArray <DbExpression>(), (Func <DbExpression, DbExpression, DbExpression>)((prev, next) => (DbExpression)prev.And(next)))); }
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_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); }