/// <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; }
/// <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; }