// <summary>
 //     Changes the s-side Function in the FunctionImportMapping
 // </summary>
 internal void ChangeModelItem(EditingContext context, Function newFunction)
 {
     var fi = FunctionImportMapping.FunctionImportName.Target;
     if (fi != null
         && FunctionImportMapping.FunctionName.Target != newFunction)
     {
         var cModel = EFExtensions.RuntimeModelRoot(FunctionImportMapping.FunctionImportName.Target) as ConceptualEntityModel;
         if (cModel != null)
         {
             var cmd = new ChangeFunctionImportCommand(
                 cModel.FirstEntityContainer as ConceptualEntityContainer,
                 fi,
                 newFunction,
                 fi.LocalName.Value,
                 fi.IsComposable.Value,
                 false,
                 null);
             // This command can be called before the provider has been registered with the 
             // resolver (e.g. Mapping Details window on a newly-opened project) - so ensure
             // provider is registered here before any commands are invoked
             var cpc = new CommandProcessorContext(
                 context, EfiTransactionOriginator.MappingDetailsOriginatorId, Resources.Tx_ChangeFuncImpMapping);
             VsUtils.EnsureProvider(cpc.Artifact);
             CommandProcessor.InvokeSingleCommand(cpc, cmd);
         }
     }
 }
        internal static void EditFunctionImport(
            EditingContext editingContext,
            FunctionImport functionImport,
            StorageEntityModel sModel,
            ConceptualEntityModel cModel,
            ConceptualEntityContainer cContainer,
            object selectedObject,
            string originatingId)
        {
            Debug.Assert(editingContext != null, "editingContext should not be null");
            Debug.Assert(!string.IsNullOrEmpty(originatingId), "originatingId should not be null or empty");

            // show dialog appropriate to framework version
            var result = ShowNewFunctionImportDialog(
                functionImport.Function,
                functionImport.LocalName.Value,
                sModel,
                cModel,
                cContainer,
                DialogsResource.NewFunctionImportDialog_EditFunctionImportTitle,
                selectedObject);

            // if user selected OK on the dialog then create the FunctionImport
            if (DialogResult.OK == result.DialogResult)
            {
                var commands = new List<Command>();
                var cp = new CommandProcessor(editingContext, originatingId, Resources.Tx_UpdateFunctionImport);
                CreateComplexTypeCommand createComplexTypeCommand = null;

                // Make the decision based on what is returned by the dialog.
                // If return type is a string and result schema is not null, that means the user would like to create a new complex type for the function import return.
                if (result.ReturnType is string
                    && result.Schema != null)
                {
                    createComplexTypeCommand = CreateMatchingFunctionImportCommand.AddCreateComplexTypeCommands(
                        sModel, result.ReturnType as string, result.Schema.RawColumns, commands);
                }
                    // If ReturnType is a complex type and result schema is not null, the complex type needs to be updated to be in sync with schema columns.
                else if (result.ReturnType is ComplexType
                         && result.Schema != null)
                {
                    var complexType = result.ReturnType as ComplexType;
                    // Create Column properties dictionary. The keys will be either property's type-mapping column name if availabe or property's name.
                    var propertiesDictionary =
                        complexType.Properties().ToDictionary(p => EdmUtils.GetFunctionImportResultColumnName(functionImport, p));
                    CreateMatchingFunctionImportCommand.AddChangeComplexTypePropertiesCommands(
                        complexType, propertiesDictionary, result.Schema.RawColumns, commands);
                }

                // construct Dictionary mapping property name to column name for FunctionImportMapping
                IDictionary<string, string> mapPropertyNameToColumnName = null;
                if (result.Schema != null)
                {
                    mapPropertyNameToColumnName =
                        ModelHelper.ConstructComplexTypePropertyNameToColumnNameMapping(result.Schema.Columns.Select(c => c.Name).ToList());
                }

                // change the FunctionImport and FunctionImportMapping to match
                ChangeFunctionImportCommand cmdFuncImpSproc = null;
                // if result.IsComposable is true then set to True, but if false then use None if existing value is None, otherwise False
                var resultIsComposable = (result.IsComposable
                                              ? BoolOrNone.TrueValue
                                              : (BoolOrNone.NoneValue == functionImport.IsComposable.Value
                                                     ? BoolOrNone.NoneValue
                                                     : BoolOrNone.FalseValue));
                if (createComplexTypeCommand == null)
                {
                    cmdFuncImpSproc = new ChangeFunctionImportCommand(
                        cContainer, functionImport, result.Function, result.FunctionName, resultIsComposable, true, result.ReturnType);
                    // Create explicit function-import result type mapping if the return type is a complex type.
                    if (result.ReturnType is ComplexType)
                    {
                        cmdFuncImpSproc.PostInvokeEvent += (o, eventArgs) =>
                            {
                                if (functionImport != null
                                    && functionImport.FunctionImportMapping != null)
                                {
                                    // CreateFunctionImportTypeMappingCommand will be no op function-import's return is unchanged.
                                    CommandProcessor.InvokeSingleCommand(
                                        cp.CommandProcessorContext
                                        ,
                                        new CreateFunctionImportTypeMappingCommand(
                                            functionImport.FunctionImportMapping, result.ReturnType as ComplexType)
                                            {
                                                CreateDefaultScalarProperties = true,
                                                PropertyNameToColumnNameMap = mapPropertyNameToColumnName
                                            });
                                }
                            };
                    }
                }
                else
                {
                    // Pass in the pre-req command to create complex type to the command.
                    cmdFuncImpSproc = new ChangeFunctionImportCommand(
                        cContainer, functionImport, result.Function, result.FunctionName,
                        resultIsComposable, createComplexTypeCommand);
                    // Create explicit function-import result type mapping if the return type is a complex type.
                    cmdFuncImpSproc.PostInvokeEvent += (o, eventArgs) =>
                        {
                            if (functionImport != null
                                && functionImport.FunctionImportMapping != null)
                            {
                                CommandProcessor.InvokeSingleCommand(
                                    cp.CommandProcessorContext,
                                    new CreateFunctionImportTypeMappingCommand(
                                        functionImport.FunctionImportMapping, createComplexTypeCommand)
                                        {
                                            CreateDefaultScalarProperties = true,
                                            PropertyNameToColumnNameMap = mapPropertyNameToColumnName
                                        });
                            }
                        };
                }
                commands.Add(cmdFuncImpSproc);
                commands.ForEach(x => cp.EnqueueCommand(x));
                cp.Invoke();
            }
        }