/// <summary>
        /// Initializes a new FunctionImportMappingComposable instance.
        /// </summary>
        /// <param name="functionImport">The model function import.</param>
        /// <param name="targetFunction">The store composable function.</param>
        /// <param name="resultMapping">The result mapping for the function import.</param>
        /// <param name="containerMapping">The parent container mapping.</param>
        public FunctionImportMappingComposable(
            EdmFunction functionImport,
            EdmFunction targetFunction,
            FunctionImportResultMapping resultMapping,
            EntityContainerMapping containerMapping)
            : base(
                Check.NotNull(functionImport, "functionImport"),
                Check.NotNull(targetFunction, "targetFunction"))
        {
            Check.NotNull(resultMapping, "resultMapping");
            Check.NotNull(containerMapping, "containerMapping");

            if (!functionImport.IsComposableAttribute)
            {
                throw new ArgumentException(Strings.NonComposableFunctionCannotBeMappedAsComposable("functionImport"));
            }

            if (!targetFunction.IsComposableAttribute)
            {
                throw new ArgumentException(Strings.NonComposableFunctionCannotBeMappedAsComposable("targetFunction"));
            }

            EdmType resultType;

            if (!MetadataHelper.TryGetFunctionImportReturnType(functionImport, 0, out resultType))
            {
                throw new ArgumentException(Strings.InvalidReturnTypeForComposableFunction);
            }

            // when this method is invoked when a CodeFirst model is being built (e.g. from a custom convention) the
            // StorageMappingItemCollection will be null. In this case we can call the converting method directly which
            // will return the correct result but the result won't be memoized. This however does not matter at this
            // point since the model is still being constructed.
            var cTypeTargetFunction =
                containerMapping.StorageMappingItemCollection != null
                ? containerMapping.StorageMappingItemCollection.StoreItemCollection.ConvertToCTypeFunction(targetFunction)
                : StoreItemCollection.ConvertFunctionSignatureToCType(targetFunction);

            var cTypeTvfElementType = TypeHelpers.GetTvfReturnType(cTypeTargetFunction);
            var sTypeTvfElementType = TypeHelpers.GetTvfReturnType(targetFunction);

            if (cTypeTvfElementType == null)
            {
                Debug.Assert(sTypeTvfElementType == null);

                throw new ArgumentException(
                          Strings.Mapping_FunctionImport_ResultMapping_InvalidSType(functionImport.Identity),
                          "functionImport");
            }

            var errors = new List <EdmSchemaError>();
            var functionImportHelper = new FunctionImportMappingComposableHelper(
                containerMapping,
                String.Empty,
                errors);

            FunctionImportMappingComposable mapping;

            if (Helper.IsStructuralType(resultType))
            {
                functionImportHelper.TryCreateFunctionImportMappingComposableWithStructuralResult(
                    functionImport,
                    cTypeTargetFunction,
                    resultMapping.SourceList,
                    cTypeTvfElementType,
                    sTypeTvfElementType,
                    LineInfo.Empty,
                    out mapping);
            }
            else
            {
                Debug.Assert(TypeSemantics.IsScalarType(resultType));
                Debug.Assert(resultMapping.TypeMappings.Count == 0);

                functionImportHelper.TryCreateFunctionImportMappingComposableWithScalarResult(
                    functionImport,
                    cTypeTargetFunction,
                    targetFunction,
                    resultType,
                    cTypeTvfElementType,
                    LineInfo.Empty,
                    out mapping);
            }

            if (mapping == null)
            {
                throw new InvalidOperationException(errors.Count > 0 ? errors[0].Message : String.Empty);
            }

            _containerMapping        = mapping._containerMapping;
            m_commandParameters      = mapping.m_commandParameters;
            m_structuralTypeMappings = mapping.m_structuralTypeMappings;
            m_targetFunctionKeys     = mapping.m_targetFunctionKeys;
            _resultMapping           = resultMapping;
        }
Example #2
0
        /// <summary>
        /// Initializes a new FunctionImportMappingComposable instance.
        /// </summary>
        /// <param name="functionImport">The model function import.</param>
        /// <param name="targetFunction">The store composable function.</param>
        /// <param name="resultMapping">The result mapping for the function import.</param>
        /// <param name="containerMapping">The parent container mapping.</param>
        public FunctionImportMappingComposable(
            EdmFunction functionImport,
            EdmFunction targetFunction,
            FunctionImportResultMapping resultMapping,
            EntityContainerMapping containerMapping)
            : base(Check.NotNull <EdmFunction>(functionImport, nameof(functionImport)), Check.NotNull <EdmFunction>(targetFunction, nameof(targetFunction)))
        {
            Check.NotNull <FunctionImportResultMapping>(resultMapping, nameof(resultMapping));
            Check.NotNull <EntityContainerMapping>(containerMapping, nameof(containerMapping));
            if (!functionImport.IsComposableAttribute)
            {
                throw new ArgumentException(Strings.NonComposableFunctionCannotBeMappedAsComposable((object)nameof(functionImport)));
            }
            if (!targetFunction.IsComposableAttribute)
            {
                throw new ArgumentException(Strings.NonComposableFunctionCannotBeMappedAsComposable((object)nameof(targetFunction)));
            }
            EdmType returnType;

            if (!MetadataHelper.TryGetFunctionImportReturnType <EdmType>(functionImport, 0, out returnType))
            {
                throw new ArgumentException(Strings.InvalidReturnTypeForComposableFunction);
            }
            EdmFunction edmFunction = containerMapping.StorageMappingItemCollection != null?containerMapping.StorageMappingItemCollection.StoreItemCollection.ConvertToCTypeFunction(targetFunction) : StoreItemCollection.ConvertFunctionSignatureToCType(targetFunction);

            RowType tvfReturnType1 = TypeHelpers.GetTvfReturnType(edmFunction);
            RowType tvfReturnType2 = TypeHelpers.GetTvfReturnType(targetFunction);

            if (tvfReturnType1 == null)
            {
                throw new ArgumentException(Strings.Mapping_FunctionImport_ResultMapping_InvalidSType((object)functionImport.Identity), nameof(functionImport));
            }
            List <EdmSchemaError> parsingErrors = new List <EdmSchemaError>();
            FunctionImportMappingComposableHelper composableHelper = new FunctionImportMappingComposableHelper(containerMapping, string.Empty, parsingErrors);
            FunctionImportMappingComposable       mapping;

            if (Helper.IsStructuralType(returnType))
            {
                composableHelper.TryCreateFunctionImportMappingComposableWithStructuralResult(functionImport, edmFunction, resultMapping.SourceList, tvfReturnType1, tvfReturnType2, (IXmlLineInfo)LineInfo.Empty, out mapping);
            }
            else
            {
                composableHelper.TryCreateFunctionImportMappingComposableWithScalarResult(functionImport, edmFunction, targetFunction, returnType, tvfReturnType1, (IXmlLineInfo)LineInfo.Empty, out mapping);
            }
            if (mapping == null)
            {
                throw new InvalidOperationException(parsingErrors.Count > 0 ? parsingErrors[0].Message : string.Empty);
            }
            this._containerMapping        = mapping._containerMapping;
            this.m_commandParameters      = mapping.m_commandParameters;
            this.m_structuralTypeMappings = mapping.m_structuralTypeMappings;
            this.m_targetFunctionKeys     = mapping.m_targetFunctionKeys;
            this._resultMapping           = resultMapping;
        }