Example #1
0
        public void GetAllPrimitiveTypes_returns_all_primitive_types_for_version()
        {
            foreach (var schemaVersion in EntityFrameworkVersion.GetAllVersions())
            {
                // remove geo spatial types for schema versions V1 and V2
                var expectedTypes =
                    PrimitiveType
                    .GetEdmPrimitiveTypes()
                    .Where(t => schemaVersion == EntityFrameworkVersion.Version3 || !IsGeoSpatialType(t))
                    .Select(t => t.Name);

                Assert.Equal(expectedTypes, ModelHelper.AllPrimitiveTypes(schemaVersion));
            }
        }
Example #2
0
        protected override void InvokeInternal(CommandProcessorContext cpc)
        {
            var artifact = cpc.EditingContext.GetEFArtifactService().Artifact;

            if (null == artifact)
            {
                Debug.Fail("null artifact not allowed");
                return;
            }

            // safety check, this should never be hit
            Debug.Assert(_schemaProcedure != null, "InvokeInternal is called when _schemaProcedure is null");
            if (null == _schemaProcedure)
            {
                throw new InvalidOperationException("InvokeInternal is called when _schemaProcedure is null.");
            }

            var cModel = artifact.ConceptualModel();

            if (null == cModel)
            {
                Debug.Fail("ConceptualEntityModel not allowed");
                return;
            }

            var cContainer = cModel.FirstEntityContainer as ConceptualEntityContainer;

            if (null == cContainer)
            {
                Debug.Fail("ConceptualEntityContainer not allowed");
                return;
            }

            var sModel = artifact.StorageModel();

            if (null == sModel)
            {
                Debug.Fail("null StorageEntityModel not allowed");
                return;
            }

            // determine matching Function
            var funcObj  = DatabaseObject.CreateFromSchemaProcedure(_schemaProcedure);
            var function = ModelHelper.FindFunction(sModel, funcObj);

            if (null == function)
            {
                // in some error scenarios where the model has not been properly created we can be asked to create a FunctionImport for a Function which does not exist
                // if so just return without creating
                return;
            }

            // do not produce FunctionImports for composable Functions unless _shouldCreateComposableFunctionImport is true
            if (false == _shouldCreateComposableFunctionImport &&
                function.IsComposable.Value)
            {
                return;
            }

            // determine FunctionImport name and make sure it is unique
            var functionImportName = OverrideNameValue;

            if (String.IsNullOrWhiteSpace(functionImportName))
            {
                if (null == function.LocalName ||
                    string.IsNullOrEmpty(function.LocalName.Value))
                {
                    Debug.Fail("null or empty LocalName attribute for matching Function " + function);
                    return;
                }
                functionImportName = ModelHelper.GetUniqueName(typeof(FunctionImport), cContainer, function.LocalName.Value);
            }
            else
            {
#if DEBUG
                string errorMessage;
                var    isUnique = ModelHelper.IsUniqueName(typeof(FunctionImport), cContainer, functionImportName, false, out errorMessage);
                Debug.Assert(isUnique, "If we gave CreateMatchingFunctionImportCommand a name, it should have been unique");
#endif
            }

            object      returnType = null;
            ComplexType existingComplexTypeReturnType = null;
            if (OverrideReturnTypeValue == null)
            {
                // get return type of the Function
                returnType = ConstructReturnType(_schemaProcedure, cModel, sModel, functionImportName);
                if (null == returnType)
                {
                    Debug.Fail("cannot determine return type for schemaProcedure " + _schemaProcedure);
                    return;
                }
            }
            else
            {
                if (OverrideReturnTypeValue.Equals(ModelConstants.NoneValue, StringComparison.Ordinal))
                {
                    returnType = Resources.NoneDisplayValueUsedForUX;
                }
                else
                {
                    var rawValue = ModelHelper.UnwrapCollectionAroundFunctionImportReturnType(OverrideReturnTypeValue);

                    // Here we attempt to find the corresponding ReturnType for the given ReturnTypeOverride.
                    // The ReturnTypeOverride will be specified as the actual XAttribute value of the return type
                    if (OverrideEntitySetValue != null)
                    {
                        if (ModelHelper.FindEntitySet(cpc.Artifact.ConceptualModel(), OverrideEntitySetValue) != null)
                        {
                            // ReturnType is an EntityType
                            returnType = ModelHelper.FindEntityTypeViaSymbol(cpc.Artifact.ConceptualModel(), rawValue);
                        }
                    }
                    else if (!ModelHelper.AllPrimitiveTypes(artifact.SchemaVersion).Contains(rawValue))
                    {
                        // ReturnType is a ComplexType
                        existingComplexTypeReturnType = ModelHelper.FindComplexType(cpc.Artifact.ConceptualModel(), rawValue);
                        returnType = existingComplexTypeReturnType;
                    }
                    else
                    {
                        returnType = rawValue;
                    }
                }
            }

            // Composable functions that do not return collections (e.g. scalar valued functions) are not supported
            // and should not be imported to the conceptual model
            if (Resources.NoneDisplayValueUsedForUX.Equals(returnType) &&
                function.IsComposable.Value)
            {
                return;
            }

            // list of commands to be executed
            IList <Command> commands = new List <Command>();

            // if return type is the name of a ComplexType then create a new matching ComplexType
            CreateComplexTypeCommand createComplexTypeCommand = null;
            if (OverrideReturnTypeValue == null &&
                returnType is string &&
                false == Resources.NoneDisplayValueUsedForUX.Equals(returnType))
            {
                createComplexTypeCommand = AddCreateComplexTypeCommands(sModel, returnType as string, _schemaProcedure.RawColumns, commands);
            }

            // if we created a ComplexType above then pass that as a pre-req to the CreateFunctionImport command,
            // otherwise just create the FunctionImport without the pre-req
            CreateFunctionImportCommand cmdFuncImp;
            if (createComplexTypeCommand == null)
            {
                if (returnType is EdmType)
                {
                    // For the case where the FunctionImport should have a return type which is not a Complex Type but
                    // simply a C-side primitive type we have to pass the _name_ of the C-side primitive type to
                    // CreateFunctionImportCommand, rather than the type itself
                    returnType = (returnType as EdmType).Name;
                }
                cmdFuncImp = new CreateFunctionImportCommand(cContainer, function, functionImportName, returnType);
            }
            else
            {
                cmdFuncImp = new CreateFunctionImportCommand(cContainer, function, functionImportName, createComplexTypeCommand);
            }

            commands.Add(cmdFuncImp);

            // now create the FunctionImportMapping to map the S-side Function to the C-side FunctionImport
            if (null != artifact.MappingModel() &&
                null != artifact.MappingModel().FirstEntityContainerMapping)
            {
                var cmdFuncImpMapping = new CreateFunctionImportMappingCommand(
                    artifact.MappingModel().FirstEntityContainerMapping, function, cmdFuncImp.Id);
                cmdFuncImpMapping.AddPreReqCommand(cmdFuncImp);
                commands.Add(cmdFuncImpMapping);

                IDictionary <string, string> mapPropertyNameToColumnName = null;
                if (_schemaProcedure != null)
                {
                    mapPropertyNameToColumnName =
                        ModelHelper.ConstructComplexTypePropertyNameToColumnNameMapping(
                            _schemaProcedure.RawColumns.Select(c => c.Name).ToList());
                }

                // Create explicit function-import result type mapping if the return type is a complex type.
                if (createComplexTypeCommand != null)
                {
                    commands.Add(
                        new CreateFunctionImportTypeMappingCommand(cmdFuncImpMapping, createComplexTypeCommand)
                    {
                        CreateDefaultScalarProperties = true,
                        PropertyNameToColumnNameMap   = mapPropertyNameToColumnName
                    });
                }
                else if (OverrideReturnTypeValue != null &&
                         existingComplexTypeReturnType != null)
                {
                    commands.Add(
                        new CreateFunctionImportTypeMappingCommand(cmdFuncImpMapping, existingComplexTypeReturnType)
                    {
                        CreateDefaultScalarProperties = true,
                        PropertyNameToColumnNameMap   = mapPropertyNameToColumnName
                    });
                }
            }

            // now invoke the list of commands
            if (null != commands)
            {
                var cp = new CommandProcessor(cpc, commands);
                cp.Invoke();

                // assign the generated FunctionImport so this command can be used as input for others
                _generatedFunctionImport = cmdFuncImp.FunctionImport;
            }
        }
        protected override void InvokeInternal(CommandProcessorContext cpc)
        {
            // safety check, this should never be hit
            if (Container == null ||
                (Function == null && ParameterDefinitions == null) ||
                ReturnSingleType == null)
            {
                throw new InvalidOperationException(
                          "InvokeInternal is called when Container or Function or ParameterDefinitions or ReturnSingleType is null");
            }

            _fi = new FunctionImport(Container, null);
            _fi.LocalName.Value = FunctionImportName;

            // if we are using a high enough EDMX schema version then set IsComposable attribute
            if (EdmFeatureManager.GetComposableFunctionImportFeatureState(_fi.Artifact.SchemaVersion).IsEnabled())
            {
                // if Function.IsComposable is true set _fi.IsComposable to true also, but if it's false then
                // leave _fi.IsComposable unset which is equivalent to false
                if (Function.IsComposable.Value)
                {
                    _fi.IsComposable.Value = BoolOrNone.TrueValue;
                }
            }

            // if the return type is an EntityType, set the EntitySet attribute to
            // that EntityType's EntitySet. For other functions, don't set
            // the EntitySet.
            var returnSingleTypeString      = ReturnSingleType as string;
            var returnSingleTypeComplexType = ReturnSingleType as ComplexType;
            var returnSingleTypeEntity      = ReturnSingleType as EntityType;

            Debug.Assert(
                returnSingleTypeString != null || returnSingleTypeComplexType != null || returnSingleTypeEntity != null,
                "Return Type for function import must be of type string or ComplexType or EntityType");

            if (returnSingleTypeString != null)
            {
                // make sure that this is a primitive type or a complex type and build a "Collection()" around it.
                if (returnSingleTypeString != Tools.XmlDesignerBase.Resources.NoneDisplayValueUsedForUX)
                {
                    var edmPrimitiveTypes = ModelHelper.AllPrimitiveTypes(_fi.Artifact.SchemaVersion);
                    if (!edmPrimitiveTypes.Contains(returnSingleTypeString))
                    {
                        var msg = string.Format(CultureInfo.CurrentCulture, Resources.INVALID_FORMAT, returnSingleTypeString);
                        throw new CommandValidationFailedException(msg);
                    }

                    _fi.ReturnTypeAsPrimitiveType.Value = String.Format(
                        CultureInfo.InvariantCulture, FunctionImport.CollectionFormat, returnSingleTypeString);
                }
            }
            else if (returnSingleTypeComplexType != null)
            {
                var complexTypes = _fi.Artifact.ConceptualModel().ComplexTypes();
                if (!complexTypes.Contains(returnSingleTypeComplexType))
                {
                    var msg = string.Format(
                        CultureInfo.CurrentCulture, Resources.INVALID_FORMAT, returnSingleTypeComplexType.NormalizedNameExternal);
                    throw new CommandValidationFailedException(msg);
                }

                _fi.ReturnTypeAsComplexType.SetRefName(returnSingleTypeComplexType);
            }
            else if (returnSingleTypeEntity != null)
            {
                _fi.EntitySet.SetRefName(returnSingleTypeEntity.EntitySet);
                _fi.ReturnTypeAsEntityType.SetRefName(returnSingleTypeEntity);
            }

            Container.AddFunctionImport(_fi);
            XmlModelHelper.NormalizeAndResolve(_fi);

            if (ParameterDefinitions != null)
            {
                UpdateFunctionImportParameters(cpc, _fi, ParameterDefinitions);
            }
            if (Function != null)
            {
                UpdateFunctionImportParameters(cpc, _fi, Function);
            }
        }