示例#1
0
 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();
 }
示例#2
0
        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();
        }
示例#5
0
        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);
        }
示例#6
0
        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))))))));
        }
示例#7
0
        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);
        }
示例#8
0
        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);
        }
示例#9
0
        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;
        }
示例#13
0
        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);
        }
示例#14
0
        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);
        }