/// <summary>
        ///     Creates a copy of Property from a Clipboard format in the specified EntityType and Position.
        /// </summary>
        /// <param name="entityType">The entity to create the property in</param>
        /// <param name="clipboardProperty"></param>
        /// <param name="insertPosition">Information where the property should be inserted to. If the parameter is null, the property will be placed as the last property of the entity.</param>
        /// <returns></returns>
        internal CopyPropertyCommand(PropertyClipboardFormat clipboardProperty, EntityType entity, InsertPropertyPosition insertPosition)
        {
            if (_insertPosition != null)
            {
                Debug.Assert(
                    entity.EntityModel.IsCSDL, "You can only set insertPosition parameter if the EntityType is a ConceptualEntityType.");
                Debug.Assert(
                    insertPosition.InsertAtProperty != null && insertPosition.InsertAtProperty.EntityType == entity,
                    "Could not create complex property in the given insertPosition because insertPosition's Entity-Type is not the same as the entity-type which the property will be created in.");
            }

            CommandValidation.ValidateEntityType(entity);
            _clipboardProperty = clipboardProperty;
            _entityType = entity;
            _insertPosition = insertPosition;
        }
        public void Invoke()
        {
            Debug.Assert(_association != null, "The Association reference is null");

            // if the association was deleted in this transaction, just return since we won't need to process it
            if (_association == null
                || _association.XObject == null)
            {
                return;
            }

            // if foreign keys aren't supported in this EF version, then we skip all processing here. 
            if (!EdmFeatureManager.GetForeignKeysInModelFeatureState(_association.Artifact.SchemaVersion).IsEnabled())
            {
                return;
            }

            Debug.Assert(_association.EntityModel.IsCSDL, "Creating foreign key properties isn't valid for SSDL associations");
            Debug.Assert(
                _association.AssociationEnds().Count == 2,
                "The association to be processed does not have 2 ends while trying to create foreign key properties");
            Debug.Assert(
                _association.AssociationSet != null,
                "The association being processed does not have a valid AssociationSet while trying to create foreign key properties");

            // remove any existing RC
            if (_association.ReferentialConstraint != null)
            {
                DeleteEFElementCommand.DeleteInTransaction(_context, _association.ReferentialConstraint);
            }

            // figure out the principal and dependent ends
            AssociationEnd principal = null;
            AssociationEnd dependent = null;
            ModelHelper.DeterminePrincipalDependentAssociationEnds(
                _association, out principal, out dependent,
                ModelHelper.DeterminePrincipalDependentAssociationEndsScenario.CreateForeignKeyProperties);

            if (principal != null
                && principal.Type.Target != null
                && dependent != null
                && dependent.Type.Target != null)
            {
                // many-to-many associations don't need foreign key properties
                if (principal.Multiplicity.Value == ModelConstants.Multiplicity_Many
                    && dependent.Multiplicity.Value == ModelConstants.Multiplicity_Many)
                {
                    return;
                }

                var principalPropertyRefs = new HashSet<Property>();
                var dependentPropertyRefs = new HashSet<Property>();

                // add properties to the dependent side

                IEnumerable<Property> pkeys;
                var cet = principal.Type.Target as ConceptualEntityType;
                if (cet != null)
                {
                    // the principal is a c-side entity
                    pkeys = cet.ResolvableTopMostBaseType.ResolvableKeys;
                }
                else
                {
                    // the principal is an s-side entity
                    pkeys = principal.Type.Target.ResolvableKeys;
                }

                foreach (var pkey in pkeys)
                {
                    // build up the foreign key name, add an '_' if the resulting name wouldn't be camel-case
                    // e.g. 
                    //  Order and Id become "OrderId"
                    //  order and id become "order_id"
                    //
                    // get a unique name for this new property
                    var fkeyName = string.Format(
                        CultureInfo.CurrentCulture, "{0}{1}{2}",
                        principal.Type.Target.LocalName.Value,
                        (char.IsUpper(pkey.LocalName.Value, 0) ? "" : "_"),
                        pkey.LocalName.Value);
                    fkeyName = ModelHelper.GetUniqueName(typeof(Property), dependent.Type.Target, fkeyName);

                    // tweak the properties; we are using the copy/paste process since we have to 
                    // copy all facets of the pk and that code does this already
                    var pcf = new PropertyClipboardFormat(pkey);
                    pcf.PropertyName = fkeyName;
                    pcf.IsKeyProperty = false;
                    pcf.IsNullable = (principal.Multiplicity.Value == ModelConstants.Multiplicity_ZeroOrOne ? true : false);
                    pcf.StoreGeneratedPattern = string.Empty;
                    pcf.GetterAccessModifier = string.Empty;
                    pcf.SetterAccessModifier = string.Empty;

                    // create the new property
                    var cmd = new CopyPropertyCommand(pcf, dependent.Type.Target);
                    CommandProcessor.InvokeSingleCommand(_context, cmd);
                    var fkey = cmd.Property;

                    // build up our list of keys
                    Debug.Assert(fkey != null, "CreateForeignKeyProperties was not able to create a foreign key");
                    if (fkey != null)
                    {
                        principalPropertyRefs.Add(pkey);
                        dependentPropertyRefs.Add(fkey);
                    }
                }

                // create the new RC
                Debug.Assert(
                    principalPropertyRefs.Count == dependentPropertyRefs.Count,
                    "List of keys are mismatched while trying to create a Ref Constraint");
                if (principalPropertyRefs.Count > 0
                    && dependentPropertyRefs.Count > 0
                    && principalPropertyRefs.Count == dependentPropertyRefs.Count)
                {
                    var cmd = new CreateReferentialConstraintCommand(principal, dependent, principalPropertyRefs, dependentPropertyRefs);
                    CommandProcessor.InvokeSingleCommand(_context, cmd);
                }
            }
        }
 /// <summary>
 ///     Creates a copy of Property from a Clipboard format in the specified ComplexType
 /// </summary>
 /// <param name="parentComplexType"></param>
 /// <param name="clipboardProperty"></param>
 /// <returns></returns>
 internal CopyComplexTypePropertyCommand(PropertyClipboardFormat clipboardProperty, ComplexType parentComplexType)
 {
     CommandValidation.ValidateComplexType(parentComplexType);
     _clipboardProperty = clipboardProperty;
     _parentComplexType = parentComplexType;
 }
 /// <summary>
 ///     Creates a copy of Property from a Clipboard format in the specified ComplexType
 /// </summary>
 /// <param name="complexType"></param>
 /// <param name="clipboardProperty"></param>
 /// <returns></returns>
 internal CopyPropertyCommand(PropertyClipboardFormat clipboardProperty, ComplexType complexType)
 {
     CommandValidation.ValidateComplexType(complexType);
     _clipboardProperty = clipboardProperty;
     _complexType = complexType;
 }
 /// <summary>
 ///     Creates a copy of Property from a Clipboard format in the specified EntityType
 /// </summary>
 /// <param name="entityType"></param>
 /// <param name="clipboardProperty"></param>
 /// <returns></returns>
 internal CopyPropertyCommand(PropertyClipboardFormat clipboardProperty, EntityType entity)
     : this(clipboardProperty, entity, null)
 {
 }
        /// <summary>
        ///     In the existing artifact create a new C-side Property
        ///     in the existing EntityType  plus a mapping based on the
        ///     C-side and S-side Properties in the temp artifact
        /// </summary>
        private Property CreateNewConceptualPropertyAndMapping(
            CommandProcessorContext cpc,
            Property cSidePropInTempArtifact, Property sSidePropInTempArtifact,
            EntityType existingEntityType)
        {
            Debug.Assert(cSidePropInTempArtifact != null, "Null C-side Property");
            Debug.Assert(cSidePropInTempArtifact.EntityType.EntityModel.IsCSDL, "cSidePropInTempArtifact must be C-side");
            Debug.Assert(sSidePropInTempArtifact != null, "Null S-side Property");
            Debug.Assert(!sSidePropInTempArtifact.EntityType.EntityModel.IsCSDL, "sSidePropInTempArtifact must be S-side");
            Debug.Assert(existingEntityType != null, "Null existing EntityType");
            Debug.Assert(existingEntityType.EntityModel.IsCSDL, "Existing EntityType must be C-side");

            var pcf = new PropertyClipboardFormat(cSidePropInTempArtifact);
            Debug.Assert(
                pcf != null, "Could not construct PropertyClipboardFormat for C-side Property " + cSidePropInTempArtifact.ToPrettyString());

            if (null == pcf)
            {
                return null;
            }
            else
            {
                // store off matching S-side property in the existing 
                // artifact for mapping below
                var sSidePropInExistingArtifact =
                    FindSSidePropInExistingArtifact(sSidePropInTempArtifact);
                Debug.Assert(
                    null != sSidePropInExistingArtifact,
                    "Cannot find S-side Property matching the one in the temp artifact " + sSidePropInTempArtifact.ToPrettyString());

                // create the C-side Property in the existing artifact
                var cmd = new CopyPropertyCommand(pcf, existingEntityType);
                CommandProcessor.InvokeSingleCommand(cpc, cmd);
                var cSidePropInExistingArtifact = cmd.Property;

                // now create the mapping for the C-side Property just created
                if (null != cSidePropInExistingArtifact
                    && null != sSidePropInExistingArtifact)
                {
                    var cmd2 =
                        new CreateFragmentScalarPropertyCommand(
                            existingEntityType,
                            cSidePropInExistingArtifact, sSidePropInExistingArtifact);
                    CommandProcessor.InvokeSingleCommand(cpc, cmd2);
                }

                return cSidePropInExistingArtifact;
            }
        }