internal FunctionImportNormalizedEntityTypeMapping( FunctionImportStructuralTypeMappingKB parent, List <FunctionImportEntityTypeMappingCondition> columnConditions, BitArray impliedEntityTypes) { this.ColumnConditions = new ReadOnlyCollection <FunctionImportEntityTypeMappingCondition>((IList <FunctionImportEntityTypeMappingCondition>)columnConditions.ToList <FunctionImportEntityTypeMappingCondition>()); this.ImpliedEntityTypes = impliedEntityTypes; this.ComplementImpliedEntityTypes = new BitArray(this.ImpliedEntityTypes).Not(); }
private bool TryConvertToEntityTypeConditionsAndPropertyMappings( EdmFunction functionImport, FunctionImportStructuralTypeMappingKB functionImportKB, int typeID, RowType cTypeTvfElementType, RowType sTypeTvfElementType, IXmlLineInfo navLineInfo, out List <ConditionPropertyMapping> typeConditions, out List <PropertyMapping> propertyMappings) { System.Data.Entity.Core.Metadata.Edm.EntityType mappedEntityType = functionImportKB.MappedEntityTypes[typeID]; typeConditions = new List <ConditionPropertyMapping>(); bool flag = false; foreach (FunctionImportNormalizedEntityTypeMapping entityTypeMapping in functionImportKB.NormalizedEntityTypeMappings.Where <FunctionImportNormalizedEntityTypeMapping>((Func <FunctionImportNormalizedEntityTypeMapping, bool>)(f => f.ImpliedEntityTypes[typeID]))) { foreach (FunctionImportEntityTypeMappingCondition mappingCondition in entityTypeMapping.ColumnConditions.Where <FunctionImportEntityTypeMappingCondition>((Func <FunctionImportEntityTypeMappingCondition, bool>)(c => c != null))) { FunctionImportEntityTypeMappingCondition condition = mappingCondition; EdmProperty column; if (sTypeTvfElementType.Properties.TryGetValue(condition.ColumnName, false, out column)) { object obj; bool? nullable; if (condition.ConditionValue.IsSentinel) { obj = (object)null; nullable = condition.ConditionValue != ValueCondition.IsNull ? new bool?(false) : new bool?(true); } else { PrimitiveType edmType = (PrimitiveType)cTypeTvfElementType.Properties[column.Name].TypeUsage.EdmType; obj = ((FunctionImportEntityTypeMappingConditionValue)condition).GetConditionValue(edmType.ClrEquivalentType, (Action)(() => FunctionImportMappingComposableHelper.AddToSchemaErrorWithMemberAndStructure(new Func <object, object, string>(Strings.Mapping_InvalidContent_ConditionMapping_InvalidPrimitiveTypeKind), column.Name, column.TypeUsage.EdmType.FullName, MappingErrorCode.ConditionError, this.m_sourceLocation, (IXmlLineInfo)condition.LineInfo, (IList <EdmSchemaError>) this.m_parsingErrors)), (Action)(() => FunctionImportMappingComposableHelper.AddToSchemaErrors(Strings.Mapping_ConditionValueTypeMismatch, MappingErrorCode.ConditionError, this.m_sourceLocation, (IXmlLineInfo)condition.LineInfo, (IList <EdmSchemaError>) this.m_parsingErrors))); if (obj == null) { flag = true; continue; } nullable = new bool?(); } typeConditions.Add(obj != null ? (ConditionPropertyMapping) new ValueConditionMapping(column, obj) : (ConditionPropertyMapping) new IsNullConditionMapping(column, nullable.Value)); } else { FunctionImportMappingComposableHelper.AddToSchemaErrorsWithMemberInfo(new Func <object, string>(Strings.Mapping_InvalidContent_Column), condition.ColumnName, MappingErrorCode.InvalidStorageMember, this.m_sourceLocation, (IXmlLineInfo)condition.LineInfo, (IList <EdmSchemaError>) this.m_parsingErrors); } } } return(!(flag | !this.TryConvertToPropertyMappings((StructuralType)mappedEntityType, cTypeTvfElementType, sTypeTvfElementType, functionImport, functionImportKB, navLineInfo, out propertyMappings))); }
internal FunctionImportNormalizedEntityTypeMapping( FunctionImportStructuralTypeMappingKB parent, List<FunctionImportEntityTypeMappingCondition> columnConditions, BitArray impliedEntityTypes) { // validate arguments DebugCheck.NotNull(parent); DebugCheck.NotNull(columnConditions); DebugCheck.NotNull(impliedEntityTypes); Debug.Assert( columnConditions.Count == parent.DiscriminatorColumns.Count, "discriminator values must be ordinally aligned with discriminator columns"); Debug.Assert( impliedEntityTypes.Length == parent.MappedEntityTypes.Count, "implied entity types must be ordinally aligned with mapped entity types"); ColumnConditions = new ReadOnlyCollection<FunctionImportEntityTypeMappingCondition>(columnConditions.ToList()); ImpliedEntityTypes = impliedEntityTypes; ComplementImpliedEntityTypes = (new BitArray(ImpliedEntityTypes)).Not(); }
internal FunctionImportNormalizedEntityTypeMapping( FunctionImportStructuralTypeMappingKB parent, List <FunctionImportEntityTypeMappingCondition> columnConditions, BitArray impliedEntityTypes) { // validate arguments DebugCheck.NotNull(parent); DebugCheck.NotNull(columnConditions); DebugCheck.NotNull(impliedEntityTypes); Debug.Assert( columnConditions.Count == parent.DiscriminatorColumns.Count, "discriminator values must be ordinally aligned with discriminator columns"); Debug.Assert( impliedEntityTypes.Length == parent.MappedEntityTypes.Count, "implied entity types must be ordinally aligned with mapped entity types"); ColumnConditions = new ReadOnlyCollection <FunctionImportEntityTypeMappingCondition>(columnConditions.ToList()); ImpliedEntityTypes = impliedEntityTypes; ComplementImpliedEntityTypes = (new BitArray(ImpliedEntityTypes)).Not(); }
internal EntityType Discriminate(object[] discriminatorValues, int resultSetIndex) { FunctionImportStructuralTypeMappingKB resultMapping = this.GetResultMapping(resultSetIndex); BitArray bitArray = new BitArray(resultMapping.MappedEntityTypes.Count, true); foreach (FunctionImportNormalizedEntityTypeMapping entityTypeMapping in resultMapping.NormalizedEntityTypeMappings) { bool flag = true; ReadOnlyCollection <FunctionImportEntityTypeMappingCondition> columnConditions = entityTypeMapping.ColumnConditions; for (int index = 0; index < columnConditions.Count; ++index) { if (columnConditions[index] != null && !columnConditions[index].ColumnValueMatchesCondition(discriminatorValues[index])) { flag = false; break; } } bitArray = !flag?bitArray.And(entityTypeMapping.ComplementImpliedEntityTypes) : bitArray.And(entityTypeMapping.ImpliedEntityTypes); } EntityType entityType = (EntityType)null; for (int index = 0; index < bitArray.Length; ++index) { if (bitArray[index]) { if (entityType != null) { throw new EntityCommandExecutionException(Strings.ADP_InvalidDataReaderUnableToDetermineType); } entityType = resultMapping.MappedEntityTypes[index]; } } if (entityType == null) { throw new EntityCommandExecutionException(Strings.ADP_InvalidDataReaderUnableToDetermineType); } return(entityType); }
internal TypeUsage GetExpectedTargetResultType(int resultSetIndex) { FunctionImportStructuralTypeMappingKB resultMapping = this.GetResultMapping(resultSetIndex); Dictionary <string, TypeUsage> source = new Dictionary <string, TypeUsage>(); IEnumerable <StructuralType> structuralTypes; if (resultMapping.NormalizedEntityTypeMappings.Count == 0) { StructuralType returnType; MetadataHelper.TryGetFunctionImportReturnType <StructuralType>(this.FunctionImport, resultSetIndex, out returnType); structuralTypes = (IEnumerable <StructuralType>) new StructuralType[1] { returnType }; } else { structuralTypes = resultMapping.MappedEntityTypes.Cast <StructuralType>(); } foreach (EdmType edmType in structuralTypes) { foreach (EdmProperty structuralMember in (IEnumerable)TypeHelpers.GetAllStructuralMembers(edmType)) { source[structuralMember.Name] = structuralMember.TypeUsage; } } foreach (string discriminatorColumn in (IEnumerable <string>) this.GetDiscriminatorColumns(resultSetIndex)) { if (!source.ContainsKey(discriminatorColumn)) { TypeUsage stringTypeUsage = TypeUsage.CreateStringTypeUsage(MetadataWorkspace.GetModelPrimitiveType(PrimitiveTypeKind.String), true, false); source.Add(discriminatorColumn, stringTypeUsage); } } return(TypeUsage.Create((EdmType) new CollectionType(TypeUsage.Create((EdmType) new RowType(source.Select <KeyValuePair <string, TypeUsage>, EdmProperty>((Func <KeyValuePair <string, TypeUsage>, EdmProperty>)(c => new EdmProperty(c.Key, c.Value)))))))); }
private bool TryConvertToPropertyMappings( StructuralType structuralType, RowType cTypeTvfElementType, RowType sTypeTvfElementType, EdmFunction functionImport, FunctionImportStructuralTypeMappingKB functionImportKB, IXmlLineInfo navLineInfo, out List <PropertyMapping> propertyMappings) { propertyMappings = new List <PropertyMapping>(); // Gather and validate structuralType property mappings. var errorFound = false; foreach (EdmProperty property in TypeHelpers.GetAllStructuralMembers(structuralType)) { // Only scalar property mappings are supported at the moment. if (!Helper.IsScalarType(property.TypeUsage.EdmType)) { var error = new EdmSchemaError( Strings.Mapping_Invalid_CSide_ScalarProperty(property.Name), (int)MappingErrorCode.InvalidTypeInScalarProperty, EdmSchemaErrorSeverity.Error, m_sourceLocation, navLineInfo.LineNumber, navLineInfo.LinePosition); m_parsingErrors.Add(error); errorFound = true; continue; } string columnName = null; IXmlLineInfo columnMappingLineInfo = null; FunctionImportReturnTypeStructuralTypeColumnRenameMapping columnRenameMapping; bool explicitPropertyMapping; if (functionImportKB.ReturnTypeColumnsRenameMapping.TryGetValue(property.Name, out columnRenameMapping)) { explicitPropertyMapping = true; columnName = columnRenameMapping.GetRename(structuralType, out columnMappingLineInfo); } else { explicitPropertyMapping = false; columnName = property.Name; } columnMappingLineInfo = columnMappingLineInfo != null && columnMappingLineInfo.HasLineInfo() ? columnMappingLineInfo : navLineInfo; EdmProperty column; if (sTypeTvfElementType.Properties.TryGetValue(columnName, false, out column)) { Debug.Assert(cTypeTvfElementType.Properties.Contains(columnName), "cTypeTvfElementType.Properties.Contains(columnName)"); var cTypeColumn = cTypeTvfElementType.Properties[columnName]; if (ValidateFunctionImportMappingResultTypeCompatibility(property.TypeUsage, cTypeColumn.TypeUsage)) { propertyMappings.Add(new ScalarPropertyMapping(property, column)); } else { var error = new EdmSchemaError( GetInvalidMemberMappingErrorMessage(property, column), (int)MappingErrorCode.IncompatibleMemberMapping, EdmSchemaErrorSeverity.Error, m_sourceLocation, columnMappingLineInfo.LineNumber, columnMappingLineInfo.LinePosition); m_parsingErrors.Add(error); errorFound = true; } } else { if (explicitPropertyMapping) { AddToSchemaErrorsWithMemberInfo( Strings.Mapping_InvalidContent_Column, columnName, MappingErrorCode.InvalidStorageMember, m_sourceLocation, columnMappingLineInfo, m_parsingErrors); errorFound = true; } else { var error = new EdmSchemaError( Strings.Mapping_FunctionImport_PropertyNotMapped( property.Name, structuralType.FullName, functionImport.Identity), (int)MappingErrorCode.MappingFunctionImportReturnTypePropertyNotMapped, EdmSchemaErrorSeverity.Error, m_sourceLocation, columnMappingLineInfo.LineNumber, columnMappingLineInfo.LinePosition); m_parsingErrors.Add(error); errorFound = true; } } } // Make sure that propertyMappings is in the order of properties of the structuredType. // The rest of the code depends on it. Debug.Assert( errorFound || TypeHelpers.GetAllStructuralMembers(structuralType).Count == propertyMappings.Count && TypeHelpers.GetAllStructuralMembers(structuralType).Cast <EdmMember>().Zip(propertyMappings) .All(ppm => ppm.Key.EdmEquals(ppm.Value.Property)), "propertyMappings order does not correspond to the order of properties in the structuredType."); return(!errorFound); }
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); }
private bool TryConvertToEntityTypeConditionsAndPropertyMappings( EdmFunction functionImport, FunctionImportStructuralTypeMappingKB functionImportKB, int typeID, RowType cTypeTvfElementType, RowType sTypeTvfElementType, IXmlLineInfo navLineInfo, out List <ConditionPropertyMapping> typeConditions, out List <PropertyMapping> propertyMappings) { var entityType = functionImportKB.MappedEntityTypes[typeID]; typeConditions = new List <ConditionPropertyMapping>(); var errorFound = false; // Gather and validate entity type conditions from the type-producing fragments. foreach (var entityTypeMapping in functionImportKB.NormalizedEntityTypeMappings.Where(f => f.ImpliedEntityTypes[typeID])) { foreach (var condition in entityTypeMapping.ColumnConditions.Where(c => c != null)) { EdmProperty column; if (sTypeTvfElementType.Properties.TryGetValue(condition.ColumnName, false, out column)) { object value; bool? isNull; if (condition.ConditionValue.IsSentinel) { value = null; if (condition.ConditionValue == ValueCondition.IsNull) { isNull = true; } else { Debug.Assert( condition.ConditionValue == ValueCondition.IsNotNull, "Only IsNull or IsNotNull condition values are expected."); isNull = false; } } else { var cTypeColumn = cTypeTvfElementType.Properties[column.Name]; Debug.Assert(cTypeColumn != null, "cTypeColumn != null"); Debug.Assert( Helper.IsPrimitiveType(cTypeColumn.TypeUsage.EdmType), "S-space columns are expected to be of a primitive type."); var cPrimitiveType = (PrimitiveType)cTypeColumn.TypeUsage.EdmType; Debug.Assert(cPrimitiveType.ClrEquivalentType != null, "Scalar Types should have associated clr type"); Debug.Assert( condition is FunctionImportEntityTypeMappingConditionValue, "Non-sentinel condition is expected to be of type FunctionImportEntityTypeMappingConditionValue."); value = ((FunctionImportEntityTypeMappingConditionValue)condition).GetConditionValue( cPrimitiveType.ClrEquivalentType, handleTypeNotComparable: () => { AddToSchemaErrorWithMemberAndStructure( Strings. Mapping_InvalidContent_ConditionMapping_InvalidPrimitiveTypeKind, column.Name, column.TypeUsage.EdmType.FullName, MappingErrorCode.ConditionError, m_sourceLocation, condition.LineInfo, m_parsingErrors); }, handleInvalidConditionValue: () => { AddToSchemaErrors( Strings.Mapping_ConditionValueTypeMismatch, MappingErrorCode.ConditionError, m_sourceLocation, condition.LineInfo, m_parsingErrors); }); if (value == null) { errorFound = true; continue; } isNull = null; } typeConditions.Add( value != null ? (ConditionPropertyMapping) new ValueConditionMapping(column, value) : new IsNullConditionMapping(column, isNull.Value)); } else { AddToSchemaErrorsWithMemberInfo( Strings.Mapping_InvalidContent_Column, condition.ColumnName, MappingErrorCode.InvalidStorageMember, m_sourceLocation, condition.LineInfo, m_parsingErrors); } } } // Gather and validate entity type property mappings. errorFound |= !TryConvertToPropertyMappings( entityType, cTypeTvfElementType, sTypeTvfElementType, functionImport, functionImportKB, navLineInfo, out propertyMappings); return(!errorFound); }
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; }
private bool TryConvertToPropertyMappings( StructuralType structuralType, RowType cTypeTvfElementType, RowType sTypeTvfElementType, EdmFunction functionImport, FunctionImportStructuralTypeMappingKB functionImportKB, IXmlLineInfo navLineInfo, out List<PropertyMapping> propertyMappings) { propertyMappings = new List<PropertyMapping>(); // Gather and validate structuralType property mappings. var errorFound = false; foreach (EdmProperty property in TypeHelpers.GetAllStructuralMembers(structuralType)) { // Only scalar property mappings are supported at the moment. if (!Helper.IsScalarType(property.TypeUsage.EdmType)) { var error = new EdmSchemaError( Strings.Mapping_Invalid_CSide_ScalarProperty(property.Name), (int)MappingErrorCode.InvalidTypeInScalarProperty, EdmSchemaErrorSeverity.Error, m_sourceLocation, navLineInfo.LineNumber, navLineInfo.LinePosition); m_parsingErrors.Add(error); errorFound = true; continue; } string columnName = null; IXmlLineInfo columnMappingLineInfo = null; FunctionImportReturnTypeStructuralTypeColumnRenameMapping columnRenameMapping; bool explicitPropertyMapping; if (functionImportKB.ReturnTypeColumnsRenameMapping.TryGetValue(property.Name, out columnRenameMapping)) { explicitPropertyMapping = true; columnName = columnRenameMapping.GetRename(structuralType, out columnMappingLineInfo); } else { explicitPropertyMapping = false; columnName = property.Name; } columnMappingLineInfo = columnMappingLineInfo != null && columnMappingLineInfo.HasLineInfo() ? columnMappingLineInfo : navLineInfo; EdmProperty column; if (sTypeTvfElementType.Properties.TryGetValue(columnName, false, out column)) { Debug.Assert(cTypeTvfElementType.Properties.Contains(columnName), "cTypeTvfElementType.Properties.Contains(columnName)"); var cTypeColumn = cTypeTvfElementType.Properties[columnName]; if (ValidateFunctionImportMappingResultTypeCompatibility(property.TypeUsage, cTypeColumn.TypeUsage)) { propertyMappings.Add(new ScalarPropertyMapping(property, column)); } else { var error = new EdmSchemaError( GetInvalidMemberMappingErrorMessage(property, column), (int)MappingErrorCode.IncompatibleMemberMapping, EdmSchemaErrorSeverity.Error, m_sourceLocation, columnMappingLineInfo.LineNumber, columnMappingLineInfo.LinePosition); m_parsingErrors.Add(error); errorFound = true; } } else { if (explicitPropertyMapping) { AddToSchemaErrorsWithMemberInfo( Strings.Mapping_InvalidContent_Column, columnName, MappingErrorCode.InvalidStorageMember, m_sourceLocation, columnMappingLineInfo, m_parsingErrors); errorFound = true; } else { var error = new EdmSchemaError( Strings.Mapping_FunctionImport_PropertyNotMapped( property.Name, structuralType.FullName, functionImport.Identity), (int)MappingErrorCode.MappingFunctionImportReturnTypePropertyNotMapped, EdmSchemaErrorSeverity.Error, m_sourceLocation, columnMappingLineInfo.LineNumber, columnMappingLineInfo.LinePosition); m_parsingErrors.Add(error); errorFound = true; } } } // Make sure that propertyMappings is in the order of properties of the structuredType. // The rest of the code depends on it. Debug.Assert( errorFound || TypeHelpers.GetAllStructuralMembers(structuralType).Count == propertyMappings.Count && TypeHelpers.GetAllStructuralMembers(structuralType).Cast<EdmMember>().Zip(propertyMappings) .All(ppm => ppm.Key.EdmEquals(ppm.Value.Property)), "propertyMappings order does not correspond to the order of properties in the structuredType."); return !errorFound; }
private bool TryConvertToEntityTypeConditionsAndPropertyMappings( EdmFunction functionImport, FunctionImportStructuralTypeMappingKB functionImportKB, int typeID, RowType cTypeTvfElementType, RowType sTypeTvfElementType, IXmlLineInfo navLineInfo, out List<ConditionPropertyMapping> typeConditions, out List<PropertyMapping> propertyMappings) { var entityType = functionImportKB.MappedEntityTypes[typeID]; typeConditions = new List<ConditionPropertyMapping>(); var errorFound = false; // Gather and validate entity type conditions from the type-producing fragments. foreach (var entityTypeMapping in functionImportKB.NormalizedEntityTypeMappings.Where(f => f.ImpliedEntityTypes[typeID])) { foreach (var condition in entityTypeMapping.ColumnConditions.Where(c => c != null)) { EdmProperty column; if (sTypeTvfElementType.Properties.TryGetValue(condition.ColumnName, false, out column)) { object value; bool? isNull; if (condition.ConditionValue.IsSentinel) { value = null; if (condition.ConditionValue == ValueCondition.IsNull) { isNull = true; } else { Debug.Assert( condition.ConditionValue == ValueCondition.IsNotNull, "Only IsNull or IsNotNull condition values are expected."); isNull = false; } } else { var cTypeColumn = cTypeTvfElementType.Properties[column.Name]; Debug.Assert(cTypeColumn != null, "cTypeColumn != null"); Debug.Assert( Helper.IsPrimitiveType(cTypeColumn.TypeUsage.EdmType), "S-space columns are expected to be of a primitive type."); var cPrimitiveType = (PrimitiveType)cTypeColumn.TypeUsage.EdmType; Debug.Assert(cPrimitiveType.ClrEquivalentType != null, "Scalar Types should have associated clr type"); Debug.Assert( condition is FunctionImportEntityTypeMappingConditionValue, "Non-sentinel condition is expected to be of type FunctionImportEntityTypeMappingConditionValue."); value = ((FunctionImportEntityTypeMappingConditionValue)condition).GetConditionValue( cPrimitiveType.ClrEquivalentType, handleTypeNotComparable: () => { AddToSchemaErrorWithMemberAndStructure( Strings. Mapping_InvalidContent_ConditionMapping_InvalidPrimitiveTypeKind, column.Name, column.TypeUsage.EdmType.FullName, MappingErrorCode.ConditionError, m_sourceLocation, condition.LineInfo, m_parsingErrors); }, handleInvalidConditionValue: () => { AddToSchemaErrors( Strings.Mapping_ConditionValueTypeMismatch, MappingErrorCode.ConditionError, m_sourceLocation, condition.LineInfo, m_parsingErrors); }); if (value == null) { errorFound = true; continue; } isNull = null; } typeConditions.Add(new ConditionPropertyMapping(null, column, value, isNull)); } else { AddToSchemaErrorsWithMemberInfo( Strings.Mapping_InvalidContent_Column, condition.ColumnName, MappingErrorCode.InvalidStorageMember, m_sourceLocation, condition.LineInfo, m_parsingErrors); } } } // Gather and validate entity type property mappings. errorFound |= !TryConvertToPropertyMappings( entityType, cTypeTvfElementType, sTypeTvfElementType, functionImport, functionImportKB, navLineInfo, out propertyMappings); return !errorFound; }
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); }
private bool TryConvertToPropertyMappings( StructuralType structuralType, RowType cTypeTvfElementType, RowType sTypeTvfElementType, EdmFunction functionImport, FunctionImportStructuralTypeMappingKB functionImportKB, IXmlLineInfo navLineInfo, out List <PropertyMapping> propertyMappings) { propertyMappings = new List <PropertyMapping>(); bool flag1 = false; foreach (EdmProperty structuralMember in (IEnumerable)TypeHelpers.GetAllStructuralMembers((EdmType)structuralType)) { if (!Helper.IsScalarType(structuralMember.TypeUsage.EdmType)) { this.m_parsingErrors.Add(new EdmSchemaError(Strings.Mapping_Invalid_CSide_ScalarProperty((object)structuralMember.Name), 2085, EdmSchemaErrorSeverity.Error, this.m_sourceLocation, navLineInfo.LineNumber, navLineInfo.LinePosition)); flag1 = true; } else { IXmlLineInfo lineInfo = (IXmlLineInfo)null; FunctionImportReturnTypeStructuralTypeColumnRenameMapping columnRenameMapping; bool flag2; string index; if (functionImportKB.ReturnTypeColumnsRenameMapping.TryGetValue(structuralMember.Name, out columnRenameMapping)) { flag2 = true; index = columnRenameMapping.GetRename((EdmType)structuralType, out lineInfo); } else { flag2 = false; index = structuralMember.Name; } lineInfo = lineInfo == null || !lineInfo.HasLineInfo() ? navLineInfo : lineInfo; EdmProperty column; if (sTypeTvfElementType.Properties.TryGetValue(index, false, out column)) { EdmProperty property = cTypeTvfElementType.Properties[index]; if (FunctionImportMappingComposableHelper.ValidateFunctionImportMappingResultTypeCompatibility(structuralMember.TypeUsage, property.TypeUsage)) { propertyMappings.Add((PropertyMapping) new ScalarPropertyMapping(structuralMember, column)); } else { this.m_parsingErrors.Add(new EdmSchemaError(FunctionImportMappingComposableHelper.GetInvalidMemberMappingErrorMessage((EdmMember)structuralMember, (EdmMember)column), 2019, EdmSchemaErrorSeverity.Error, this.m_sourceLocation, lineInfo.LineNumber, lineInfo.LinePosition)); flag1 = true; } } else if (flag2) { FunctionImportMappingComposableHelper.AddToSchemaErrorsWithMemberInfo(new Func <object, string>(Strings.Mapping_InvalidContent_Column), index, MappingErrorCode.InvalidStorageMember, this.m_sourceLocation, lineInfo, (IList <EdmSchemaError>) this.m_parsingErrors); flag1 = true; } else { this.m_parsingErrors.Add(new EdmSchemaError(Strings.Mapping_FunctionImport_PropertyNotMapped((object)structuralMember.Name, (object)structuralType.FullName, (object)functionImport.Identity), 2104, EdmSchemaErrorSeverity.Error, this.m_sourceLocation, lineInfo.LineNumber, lineInfo.LinePosition)); flag1 = true; } } } return(!flag1); }