internal override void Invoke(CommandProcessorContext cpc)
 {
     var cmd = new CreateConceptualAssociationCommand(
         _dialog.AssociationName,
         _dialog.End1Entity,
         _dialog.End1Multiplicity,
         _dialog.End1NavigationPropertyName,
         _dialog.End2Entity,
         _dialog.End2Multiplicity,
         _dialog.End2NavigationPropertyName,
         false, // uniquify names
         _dialog.CreateForeignKeyProperties);
     CommandProcessor.InvokeSingleCommand(cpc, cmd);
     Debug.Assert(cmd.CreatedAssociation != null);
 }
        private void CopyAssociation(
            CommandProcessorContext cpc, BaseEntityModel model, AssociationClipboardFormat clipboardAssociation
            , Dictionary<EntityTypeClipboardFormat, EntityType> entitiesMap)
        {
            var associationName = ModelHelper.GetUniqueName(typeof(Association), model, clipboardAssociation.AssociationName);
            var clipboardEntity1 = clipboardAssociation.ClipboardEntity1;
            var clipboardEntity2 = clipboardAssociation.ClipboardEntity2;

            var entity1 = entitiesMap[clipboardEntity1] as ConceptualEntityType;
            var entity2 = entitiesMap[clipboardEntity2] as ConceptualEntityType;

            Debug.Assert(entity1 != null, "entity1 is not a ConceptualEntityType");
            Debug.Assert(entity2 != null, "entity2 is not a ConceptualEntityType");

            var navigationPropertyEntity1 = clipboardEntity1.GetNavigationPropertyClipboard(
                clipboardAssociation.AssociationName, clipboardAssociation.AssociationEndRole1);
            var navigationPropertyEntity2 = clipboardEntity2.GetNavigationPropertyClipboard(
                clipboardAssociation.AssociationName, clipboardAssociation.AssociationEndRole2);

            var navigationPropertyName1 = navigationPropertyEntity1 != null
                                              ? ModelHelper.GetUniqueConceptualPropertyName(navigationPropertyEntity1.PropertyName, entity1)
                                              : null;
            string navigationPropertyName2 = null;
            if (entity1 == entity2)
            {
                // if this is a self-association then the NavProp for end2 needs a different name from end1
                navigationPropertyName2 =
                    ModelHelper.GetUniqueConceptualPropertyName(
                        (navigationPropertyEntity2 != null ? navigationPropertyEntity2.PropertyName : entity1.LocalName.Value), entity2,
                        new HashSet<string> { navigationPropertyName1 });
            }
            else
            {
                navigationPropertyName2 =
                    ModelHelper.GetUniqueConceptualPropertyName(
                        (navigationPropertyEntity2 != null ? navigationPropertyEntity2.PropertyName : entity1.LocalName.Value), entity2);
            }
            var cmd = new CreateConceptualAssociationCommand(
                associationName, entity1, clipboardAssociation.Multiplicity1, navigationPropertyName1, entity2,
                clipboardAssociation.Multiplicity2, navigationPropertyName2, true, false);
            CommandProcessor.InvokeSingleCommand(cpc, cmd);

            // copy nav prop facets & structured annotations
            if (navigationPropertyEntity1 != null)
            {
                var np1 = entity1.FindNavigationPropertyForEnd(cmd.End1);
                CommandProcessor.InvokeSingleCommand(
                    cpc,
                    new SetNavigationPropertyFacetsCommand(
                        np1, navigationPropertyEntity1.GetterAccessModifier, navigationPropertyEntity1.SetterAccessModifier));
                AddAnnotations(navigationPropertyEntity1, np1);
            }
            if (navigationPropertyEntity2 != null)
            {
                var np2 = entity2.FindNavigationPropertyForEnd(cmd.End2);
                CommandProcessor.InvokeSingleCommand(
                    cpc,
                    new SetNavigationPropertyFacetsCommand(
                        np2, navigationPropertyEntity2.GetterAccessModifier, navigationPropertyEntity2.SetterAccessModifier));
                AddAnnotations(navigationPropertyEntity2, np2);
            }

            if (clipboardAssociation.ReferentialConstraint != null)
            {
                EntityType principal;
                EntityType dependent;
                if (entity1 == FindEntityByClipboardName(clipboardAssociation.ReferentialConstraint.PrincipalEntityName, entitiesMap))
                {
                    principal = entity1;
                    dependent = entity2;
                }
                else
                {
                    Debug.Assert(
                        entity2 == FindEntityByClipboardName(clipboardAssociation.ReferentialConstraint.PrincipalEntityName, entitiesMap),
                        "could not find entity using clipboard name " + clipboardAssociation.ReferentialConstraint.PrincipalEntityName);

                    principal = entity2;
                    dependent = entity1;
                }
                IEnumerable<Property> principalPropertyList = null;
                IEnumerable<Property> dependentPropertyList = null;
                var associationEnds = cmd.CreatedAssociation.AssociationEnds();
                if (associationEnds.Count == 2
                    && (principalPropertyList =
                        ModelHelper.FindProperties(principal, clipboardAssociation.ReferentialConstraint.PrincipalProperties)) != null
                    && (dependentPropertyList =
                        ModelHelper.FindProperties(dependent, clipboardAssociation.ReferentialConstraint.DependentProperties)) != null)
                {
                    var refCmd = new CreateReferentialConstraintCommand(
                        associationEnds[0], associationEnds[1], principalPropertyList, dependentPropertyList
                        );
                    CommandProcessor.InvokeSingleCommand(cpc, refCmd);
                    AddAnnotations(clipboardAssociation.ReferentialConstraint, refCmd.ReferentialConstraint);
                }
            }

            // add structured annotations to the association
            AddAnnotations(clipboardAssociation, cmd.CreatedAssociation);
        }
            AddReferentialConstraintForAssociation(
            CommandProcessorContext cpc, CreateConceptualAssociationCommand cmd, bool end1IsPrincipalEnd,
            List<Property> principalPropertiesInExistingArtifact, List<Property> dependentPropertiesInExistingArtifact)
        {
            if (cmd.End1 == null)
            {
                Debug.Fail("Should not have null AssociationEnd End1 from CreateConceptualAssociationCommand");
                return null;
            }
            else if (cmd.End2 == null)
            {
                Debug.Fail("Should not have null AssociationEnd End2 from CreateConceptualAssociationCommand");
                return null;
            }

            //assign principal and dependent ends
            var principalEndInExistingArtifact = end1IsPrincipalEnd ? cmd.End1 : cmd.End2;
            var dependentEndInExistingArtifact = end1IsPrincipalEnd ? cmd.End2 : cmd.End1;

            // now create the referential constraint
            var rcCmd = new CreateReferentialConstraintCommand(
                principalEndInExistingArtifact, dependentEndInExistingArtifact,
                principalPropertiesInExistingArtifact, dependentPropertiesInExistingArtifact);
            CommandProcessor.InvokeSingleCommand(cpc, rcCmd);
            var newRC = rcCmd.ReferentialConstraint;

            return newRC;
        }
        internal static Association CreateAssociationAndAssociationSetWithDefaultNames(
            CommandProcessorContext cpc, ConceptualEntityType end1Entity, ConceptualEntityType end2Entity)
        {
            var service = cpc.EditingContext.GetEFArtifactService();
            var artifact = service.Artifact;

            // the model that we want to add the association to
            var model = artifact.ConceptualModel();
            if (model == null)
            {
                throw new CannotLocateParentItemException();
            }

            // Should have discovered the association name through the behavior service. Going back to default
            var associationName = ModelHelper.GetUniqueName(
                typeof(Association), model, end1Entity.LocalName.Value + end2Entity.LocalName.Value);

            // pluralization service is based on English only for Dev10
            IPluralizationService pluralizationService = null;
            var pluralize = ModelHelper.GetDesignerPropertyValueFromArtifactAsBool(
                OptionsDesignerInfo.ElementName,
                OptionsDesignerInfo.AttributeEnablePluralization, OptionsDesignerInfo.EnablePluralizationDefault, artifact);
            if (pluralize)
            {
                pluralizationService = DependencyResolver.GetService<IPluralizationService>();
            }

            var end1Multiplicity = ModelConstants.Multiplicity_One;
            var end2Multiplicity = ModelConstants.Multiplicity_Many;

            var proposedEnd1NavPropName = ModelHelper.ConstructProposedNavigationPropertyName(
                pluralizationService, end2Entity.LocalName.Value, end2Multiplicity);
            var end1NavigationPropertyName = ModelHelper.GetUniqueConceptualPropertyName(proposedEnd1NavPropName, end1Entity);
            var proposedEnd2NavPropName = ModelHelper.ConstructProposedNavigationPropertyName(
                pluralizationService, end1Entity.LocalName.Value, end1Multiplicity);
            var end2NavigationPropertyName = ModelHelper.GetUniqueConceptualPropertyName(
                proposedEnd2NavPropName, end2Entity, new HashSet<string> { end1NavigationPropertyName });

            var cac = new CreateConceptualAssociationCommand(
                associationName,
                end1Entity, end1Multiplicity, end1NavigationPropertyName,
                end2Entity, end2Multiplicity, end2NavigationPropertyName,
                false, // uniquify names
                false); // create foreign key properties
            var cp = new CommandProcessor(cpc, cac);
            cp.Invoke();

            return cac.CreatedAssociation;
        }
        /// <summary>
        ///     Clone the Association with its ReferentialConstraint (if available), AssociationSet
        ///     and AssociationSetMapping. If the ReferentialConstraint is available in the temp artifact
        ///     but we cannot find matching properties in the existing artifact then the whole Association
        ///     (and AssociationSet and AssociationSetMapping) will not be cloned, a warning message will
        ///     be issued but otherwise the process is not stopped.
        ///     But if the Association cannot be created for any other reason that's an error and an
        ///     UpdateModelFromDatabaseException will be thrown.
        /// </summary>
        /// <param name="cpc">CommandProcessorContext for the commands to be issued</param>
        /// <param name="existingArtifact">the existing artifact in which to make these changes</param>
        /// <param name="assocInTempArtifact">the Association in the temp artifact to be cloned</param>
        /// <param name="end1InTempArtifact">the end of the Association in the temp artifact to be cloned to be treated as End1</param>
        /// <param name="end2InTempArtifact">the end of the Association in the temp artifact to be cloned to be treated as End2</param>
        /// <param name="navProp1InTempArtifact">the NavigationProperty for End1 in the temp artifact to be cloned</param>
        /// <param name="navProp2InTempArtifact">the NavigationProperty for End2 in the temp artifact to be cloned</param>
        /// <param name="end1EntityTypeInExistingArtifact">the EntityType in the existing artifact matching the End1 target in the temp artifact</param>
        /// <param name="end2EntityTypeInExistingArtifact">the EntityType in the existing artifact matching the End2 target in the temp artifact</param>
        /// <param name="tempArtifactCEntityTypeToNewCEntityTypeInExistingArtifact">
        ///     a Dictionary mapping temp artifact EntityTypes which have
        ///     been identified as new to their equivalent in the existing artifact
        /// </param>
        private void CloneAssociation(
            CommandProcessorContext cpc, EFArtifact existingArtifact, Association assocInTempArtifact,
            AssociationEnd end1InTempArtifact, AssociationEnd end2InTempArtifact,
            NavigationProperty navProp1InTempArtifact, NavigationProperty navProp2InTempArtifact,
            ConceptualEntityType end1EntityTypeInExistingArtifact, ConceptualEntityType end2EntityTypeInExistingArtifact,
            Dictionary<EntityType, EntityType> tempArtifactCEntityTypeToNewCEntityTypeInExistingArtifact)
        {
            Association newAssocInExistingArtifact = null;
            AssociationEnd newAssocEnd1 = null;
            AssociationEnd newAssocEnd2 = null;
            if (assocInTempArtifact.ReferentialConstraint == null)
            {
                // if there is no ReferentialConstraint to clone then just try to 
                // create the Association and AssociationSet
                var cmd = new CreateConceptualAssociationCommand(
                    assocInTempArtifact.LocalName.Value,
                    end1EntityTypeInExistingArtifact, end1InTempArtifact.Multiplicity.Value, navProp1InTempArtifact.LocalName.Value,
                    end2EntityTypeInExistingArtifact, end2InTempArtifact.Multiplicity.Value, navProp2InTempArtifact.LocalName.Value,
                    true, false);
                CommandProcessor.InvokeSingleCommand(cpc, cmd);
                newAssocInExistingArtifact = cmd.CreatedAssociation;
                newAssocEnd1 = cmd.End1;
                newAssocEnd2 = cmd.End2;
            }
            else
            {
                // There is a ReferentialConstraint - so we need to check whether we can find matching properties
                // for the Principal and Dependent roles of the ReferentialConstraint. If we can't find
                // matching properties then log a warning message and return. Otherwise attempt to create
                // the Association (and its AssociationSet) followed by a matching ReferentialConstraint.
                //
                // Note: ShouldCreateAssociationGivenReferentialConstraint() produces 2 sets of information:
                // (1) the sets of matching properties to use if we can find matching properties for the Principal
                // and Dependent roles, and (2) the sets of property names to include in the error message if 
                // we cannot find matching properties for the Principal and Dependent roles.
                // If ShouldCreateAssociationGivenReferentialConstraint() returns true we use the first set of
                // information to create the ReferentialConstraint after having created the Association and
                // AssociationSet. If it returns false we use the second set of information to construct the
                // warning message.
                var refConstraintInTempArtifact = assocInTempArtifact.ReferentialConstraint;
                bool end1IsPrincipalEnd;
                List<Property> principalPropertiesInExistingArtifact;
                List<Property> dependentPropertiesInExistingArtifact;
                List<string> unfoundPrincipalProperties;
                List<string> unfoundDependentProperties;
                if (ShouldCreateAssociationGivenReferentialConstraint(
                    refConstraintInTempArtifact, end1InTempArtifact,
                    end2InTempArtifact, end1EntityTypeInExistingArtifact, end2EntityTypeInExistingArtifact, out end1IsPrincipalEnd,
                    out principalPropertiesInExistingArtifact, out dependentPropertiesInExistingArtifact,
                    out unfoundPrincipalProperties, out unfoundDependentProperties))
                {
                    // create the new Association and AssociationSet
                    var cmd = new CreateConceptualAssociationCommand(
                        assocInTempArtifact.LocalName.Value,
                        end1EntityTypeInExistingArtifact, end1InTempArtifact.Multiplicity.Value, navProp1InTempArtifact.LocalName.Value,
                        end2EntityTypeInExistingArtifact, end2InTempArtifact.Multiplicity.Value, navProp2InTempArtifact.LocalName.Value,
                        true, false);
                    CommandProcessor.InvokeSingleCommand(cpc, cmd);
                    newAssocInExistingArtifact = cmd.CreatedAssociation;
                    newAssocEnd1 = cmd.End1;
                    newAssocEnd2 = cmd.End2;

                    // Add in the ReferentialConstraint for the new Association
                    if (null != newAssocInExistingArtifact)
                    {
                        AddReferentialConstraintForAssociation(
                            cpc, cmd, end1IsPrincipalEnd, principalPropertiesInExistingArtifact, dependentPropertiesInExistingArtifact);
                    }
                }
                else
                {
                    // Unable to find matching properties for the Principal and Dependent roles of 
                    // the ReferentialConstraint. So log a warning message.
                    newAssocInExistingArtifact = null;
                    EntityType principalEndEntityType = end1IsPrincipalEnd
                                                            ? end1EntityTypeInExistingArtifact
                                                            : end2EntityTypeInExistingArtifact;
                    EntityType dependentEndEntityType = end1IsPrincipalEnd
                                                            ? end2EntityTypeInExistingArtifact
                                                            : end1EntityTypeInExistingArtifact;
                    LogWarningMessageForReferentialConstraintProperties(
                        assocInTempArtifact.LocalName.Value,
                        principalEndEntityType, dependentEndEntityType, unfoundPrincipalProperties, unfoundDependentProperties);

                    // having logged the warning message we do not need to attempt to create
                    // the AssociationSetMapping nor throw an exception due to the lack of the
                    // created Association - so just return
                    return;
                }
            }

            // if we have failed to create an Association at this stage that's a serious error
            // so throw an exception to indicate the failure
            if (null == newAssocInExistingArtifact)
            {
                throw new UpdateModelFromDatabaseException(
                    string.Format(
                        CultureInfo.CurrentCulture,
                        Resources.UpdateFromDatabaseCannotCreateAssociation,
                        assocInTempArtifact.ToPrettyString()));
            }

            // update OnDeleteActions to match temp artifact
            UpdateOnDeleteAction(cpc, newAssocEnd1, end1InTempArtifact);
            UpdateOnDeleteAction(cpc, newAssocEnd2, end2InTempArtifact);

            // add a new AssociationSetMapping for the new Association
            AddAssociationSetMappingForConceptualAssociation(
                cpc, existingArtifact, assocInTempArtifact,
                newAssocInExistingArtifact, tempArtifactCEntityTypeToNewCEntityTypeInExistingArtifact);
        }