protected override void InvokeInternal(CommandProcessorContext cpc)
        {
            // make sure that there isn't an ETM of this kind already
            var entityTypeMapping = ModelHelper.FindEntityTypeMapping(cpc, _entityType, _kind, false);

            Debug.Assert(entityTypeMapping == null, "We are calling CreateEntityTypeMappingCommand and there is already one of this Kind");
            if (entityTypeMapping != null)
            {
                _created = entityTypeMapping;
                return;
            }

            // see if we can get the EntitySetMapping for our entity (if we weren't passed it)
            if (_entitySetMapping == null)
            {
                var ces = _entityType.EntitySet as ConceptualEntitySet;
                Debug.Assert(ces != null, "_entityType.EntitySet should be a ConceptualEntitySet");

                // find the EntitySetMapping for this type (V1 assumption is that there is only ESM per ES)
                EntitySetMapping esm = null;
                foreach (var depMapping in ces.GetAntiDependenciesOfType <EntitySetMapping>())
                {
                    esm = depMapping;
                    break;
                }

                _entitySetMapping = esm;
            }

            // if we still don't have an ESM, create one
            if (_entitySetMapping == null)
            {
                var cmd = new CreateEntitySetMappingCommand(
                    _entityType.Artifact.MappingModel().FirstEntityContainerMapping,
                    _entityType.EntitySet as ConceptualEntitySet);
                CommandProcessor.InvokeSingleCommand(cpc, cmd);
                _entitySetMapping = cmd.EntitySetMapping;
            }
            Debug.Assert(
                _entitySetMapping != null,
                "_entitySetMapping should not be null - we have been unable to find or create an EntitySetMapping");

            // create the ETM
            var etm = new EntityTypeMapping(_entitySetMapping, null, _kind);

            etm.TypeName.SetRefName(_entityType);
            _entitySetMapping.AddEntityTypeMapping(etm);

            XmlModelHelper.NormalizeAndResolve(etm);

            _created = etm;
        }
        protected override void InvokeInternal(CommandProcessorContext cpc)
        {
            // safety check, this should never be hit
            Debug.Assert(
                EntityToBeDerived != null && BaseType != null, "InvokeInternal is called when EntityToBeDerived or BaseType is null");

            if (EntityToBeDerived == null ||
                BaseType == null)
            {
                throw new InvalidOperationException("InvokeInternal is called when EntityToBeDerived or BaseType is null");
            }

            if (EntityToBeDerived.EntitySet != null)
            {
                // since we are creating an inheritance, we need to delete EntitySet(s) for entityToBeDerived,
                // before we do this, move any EntityTypeMappings to the base type's EntitySetMapping
                var entitySetToDelete        = EntityToBeDerived.EntitySet as ConceptualEntitySet;
                var entitySetMappingToDelete = entitySetToDelete.EntitySetMapping;

                // if there isn't an ESM, there won't be anything to move
                if (entitySetMappingToDelete != null)
                {
                    var entitySetOfBaseType = BaseType.EntitySet as ConceptualEntitySet;
                    if (entitySetOfBaseType != null)
                    {
                        // get the base type's ESM (if it doesn't exist, create one)
                        var entitySetMappingOfBaseType = entitySetOfBaseType.EntitySetMapping;
                        if (entitySetMappingOfBaseType == null)
                        {
                            var entityContainer = EntityToBeDerived.EntityModel.EntityContainer;
                            Debug.Assert(entityContainer != null, "EntityToBeDerived should have an Entity Container");

                            var createESM = new CreateEntitySetMappingCommand(entityContainer.EntityContainerMapping, entitySetOfBaseType);
                            CommandProcessor.InvokeSingleCommand(cpc, createESM);
                            entitySetMappingOfBaseType = createESM.EntitySetMapping;
                        }

                        // move all of the ETMs
                        var etms = new List <EntityTypeMapping>();
                        etms.AddRange(entitySetMappingToDelete.EntityTypeMappings());

                        foreach (var etm in etms)
                        {
                            // here, to work around an xml editor bug, we clone the entity type mapping, instead of re-parenting it
                            etm.Clone(entitySetMappingOfBaseType);

                            // The old EntityTyepMapping will be deleted when we delete the entity set below.
                        }
                    }
                }

                // now we can delete the entity set, which will delete the ESM too
                DeleteEFElementCommand.DeleteInTransaction(cpc, entitySetToDelete);
            }

            // remove all properties from derived entity's key (it will inherit the base type's keys now)
            if (EntityToBeDerived.Key != null)
            {
                var propertyRefs = new List <PropertyRef>(EntityToBeDerived.Key.PropertyRefs);
                foreach (var propertyRef in propertyRefs)
                {
                    var property = propertyRef.Name.Target;
                    if (property != null)
                    {
                        var setKey = new SetKeyPropertyCommand(property, false, false, true);
                        CommandProcessor.InvokeSingleCommand(cpc, setKey);
                    }
                }
            }

            // set the base type
            EntityToBeDerived.BaseType.SetRefName(BaseType);

            //
            // if there is a referential constraint, then update any principals in the ref constraint to
            // point to properties in the new entity type.
            //
            foreach (var end in EntityToBeDerived.GetAntiDependenciesOfType <AssociationEnd>())
            {
                foreach (var role in end.GetAntiDependenciesOfType <ReferentialConstraintRole>())
                {
                    var rc = role.Parent as ReferentialConstraint;
                    if (rc != null &&
                        rc.Principal == role)
                    {
                        //
                        // this is the principal, so we want to update any keys in RC to reflect new keys
                        // in the new base type.  If the number of keys don't match, we'll delete any leftovers
                        //
                        var keys = BaseType.ResolvableTopMostBaseType.ResolvableKeys.GetEnumerator();
                        foreach (var pr in rc.Principal.PropertyRefs)
                        {
                            if (keys.MoveNext())
                            {
                                // update this property ref to reflect the new key in the derived type
                                pr.Name.SetRefName(keys.Current);
                                ItemBinding[] bindings = { pr.Name };
                                CheckArtifactBindings.ScheduleBindingsForRebind(cpc, bindings);
                            }
                            else
                            {
                                // no more keys in the new base type, so delete this property ref & it's peer
                                // in the dependent section
                                Command cmd = new DeleteReferentialConstraintPropertyRefCommand(pr);
                                // don't invoke this command now, as it will modify the collection we're iterating over
                                CommandProcessor.EnqueueCommand(cmd);
                            }
                        }
                    }
                }
            }

            // rebind and verify
            EntityToBeDerived.BaseType.Rebind();
            Debug.Assert(
                EntityToBeDerived.BaseType.Status == BindingStatus.Known,
                "EntityToBeDerived.BaseType.Status should be BindingStatus.Known, instead it is "
                + EntityToBeDerived.BaseType.Status.ToString());
        }
Exemplo n.º 3
0
        protected override void InvokeInternal(CommandProcessorContext cpc)
        {
            // safety check, this should never be hit
            Debug.Assert(_derivedType != null, "InvokeInternal is called when DerivedType is null.");
            if (_derivedType == null)
            {
                throw new InvalidOperationException("InvokeInternal is called when DerivedType is null.");
            }

            // store off some local variables
            var baseType             = _derivedType.BaseType.Target;
            var baseEntitySet        = baseType.EntitySet as ConceptualEntitySet;
            var baseEntitySetMapping = (baseEntitySet == null ? null : baseEntitySet.EntitySetMapping);

            // save off a HashSet of all base types up the inheritance tree for searching later
            var allBaseTypes = new HashSet <EntityType>();

            for (var baseEntityType = baseType; baseEntityType != null; baseEntityType = baseEntityType.BaseType.Target)
            {
                allBaseTypes.Add(baseEntityType);
            }

            // set up list of all derived types down the inheritance tree
            var derivedAndAllDerivedTypes = new List <ConceptualEntityType>();

            derivedAndAllDerivedTypes.Add(_derivedType);
            derivedAndAllDerivedTypes.AddRange(_derivedType.ResolvableAllDerivedTypes);

            // remove any mappings which refer to properties which were inherited as these will
            // no longer be valid when the inheritance is deleted (and would cause the Mapping Details
            // window to open in non-edit mode). This must be done _before_ proceeding to clone the
            // EntityTypeMapping below and before we delete the inheritance (i.e. before the
            // DefaultableValue Target becomes unresolved).
            var scalarPropsToDelete = new List <ScalarProperty>();

            if (allBaseTypes.Count > 0)
            {
                foreach (EntityType et in derivedAndAllDerivedTypes)
                {
                    foreach (var etm in et.GetAntiDependenciesOfType <EntityTypeMapping>())
                    {
                        foreach (var mf in etm.MappingFragments())
                        {
                            foreach (var sp in mf.AllScalarProperties())
                            {
                                var prop = sp.Name.Target;
                                if (prop != null)
                                {
                                    // find EntityType of which this Property is a member
                                    var propEntityType = prop.GetParentOfType(typeof(EntityType)) as EntityType;
                                    if (propEntityType != null &&
                                        allBaseTypes.Contains(propEntityType))
                                    {
                                        // sp references a Property of an EntityType which will no longer
                                        // be in the inheritance hierarchy - so delete the mapping
                                        scalarPropsToDelete.Add(sp);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // cannot delete the ScalarProperty while enumerating over them - so instead delete in separate loop below
            foreach (var sp in scalarPropsToDelete)
            {
                DeleteEFElementCommand.DeleteInTransaction(cpc, sp);
            }

            // remove the inheritance
            _derivedType.BaseType.SetRefName(null);

            // re-resolve the derived type.  This will set the state of the _derivedType to be resolved (it could be unresolved because base-type binding could have been a duplicate or unknown binding).
            _derivedType.State = EFElementState.Normalized;
            _derivedType.Resolve(_derivedType.Artifact.ArtifactSet);

            // the entity container we want to add it to
            var entityContainer = _derivedType.EntityModel.EntityContainer;

            Debug.Assert(entityContainer != null, "DerivedType does not have an Entity Container");

            // since this type no longer derives, it is stand alone and needs its own entity set
            // derive a name for the new entity set and create it
            var trialSetName = ModelHelper.ConstructProposedEntitySetName(_derivedType.Artifact, _derivedType.LocalName.Value);
            var ces          = new CreateEntitySetCommand(trialSetName, _derivedType, true);

            CommandProcessor.InvokeSingleCommand(cpc, ces);
            var newEntitySet = ces.EntitySet as ConceptualEntitySet;

            // if the old entityset had mappings, then some may need to be moved
            if (baseEntitySetMapping != null)
            {
                // create a new EntitySetMapping for the new EntitySet that we made for the formally derivedType
                var createESM = new CreateEntitySetMappingCommand(entityContainer.EntityContainerMapping, newEntitySet);
                CommandProcessor.InvokeSingleCommand(cpc, createESM);
                var newEntitySetMapping = createESM.EntitySetMapping;

                // this type no longer derives from the type it used to, so its mappings can no longer
                // exist under the old EntitySetMapping, so we need to move them
                // move any EntityTypeMappings from the old EntitySetMapping used by the former base type
                // to the new one created for the new EntitySet and EntitySetMapping
                foreach (EntityType changingType in derivedAndAllDerivedTypes)
                {
                    var etms = new List <EntityTypeMapping>();
                    etms.AddRange(changingType.GetAntiDependenciesOfType <EntityTypeMapping>());

                    foreach (var etm in etms)
                    {
                        // here, to work around an xml editor bug, we clone the entity type mapping, instead of re-parenting it
                        var newetm = etm.Clone(newEntitySetMapping);

                        // now delete the old entity type mapping & dispose it.
                        DeleteEFElementCommand.DeleteInTransaction(cpc, etm);
                    }
                }
            }

            //
            //  if there are any referential constraints properties whose principal ends refer to keys in the
            //  old derived type, delete them
            //
            foreach (var end in _derivedType.GetAntiDependenciesOfType <AssociationEnd>())
            {
                foreach (var role in end.GetAntiDependenciesOfType <ReferentialConstraintRole>())
                {
                    var rc = role.Parent as ReferentialConstraint;
                    if (rc != null &&
                        rc.Principal == role)
                    {
                        foreach (var pr in rc.Principal.PropertyRefs)
                        {
                            Command cmd = new DeleteReferentialConstraintPropertyRefCommand(pr);
                            // don't invoke this command now, as it will modify the collection we're iterating over
                            CommandProcessor.EnqueueCommand(cmd);
                        }
                    }
                }
            }
        }
        protected override void InvokeInternal(CommandProcessorContext cpc)
        {
            // safety check, this should never be hit
            Debug.Assert(
                EntityToBeDerived != null && BaseType != null, "InvokeInternal is called when EntityToBeDerived or BaseType is null");

            if (EntityToBeDerived == null
                || BaseType == null)
            {
                throw new InvalidOperationException("InvokeInternal is called when EntityToBeDerived or BaseType is null");
            }

            if (EntityToBeDerived.EntitySet != null)
            {
                // since we are creating an inheritance, we need to delete EntitySet(s) for entityToBeDerived, 
                // before we do this, move any EntityTypeMappings to the base type's EntitySetMapping
                var entitySetToDelete = EntityToBeDerived.EntitySet as ConceptualEntitySet;
                var entitySetMappingToDelete = entitySetToDelete.EntitySetMapping;

                // if there isn't an ESM, there won't be anything to move
                if (entitySetMappingToDelete != null)
                {
                    var entitySetOfBaseType = BaseType.EntitySet as ConceptualEntitySet;
                    if (entitySetOfBaseType != null)
                    {
                        // get the base type's ESM (if it doesn't exist, create one)
                        var entitySetMappingOfBaseType = entitySetOfBaseType.EntitySetMapping;
                        if (entitySetMappingOfBaseType == null)
                        {
                            var entityContainer = EntityToBeDerived.EntityModel.EntityContainer;
                            Debug.Assert(entityContainer != null, "EntityToBeDerived should have an Entity Container");

                            var createESM = new CreateEntitySetMappingCommand(entityContainer.EntityContainerMapping, entitySetOfBaseType);
                            CommandProcessor.InvokeSingleCommand(cpc, createESM);
                            entitySetMappingOfBaseType = createESM.EntitySetMapping;
                        }

                        // move all of the ETMs
                        var etms = new List<EntityTypeMapping>();
                        etms.AddRange(entitySetMappingToDelete.EntityTypeMappings());

                        foreach (var etm in etms)
                        {
                            // here, to work around an xml editor bug, we clone the entity type mapping, instead of re-parenting it
                            etm.Clone(entitySetMappingOfBaseType);

                            // The old EntityTyepMapping will be deleted when we delete the entity set below.  
                        }
                    }
                }

                // now we can delete the entity set, which will delete the ESM too
                DeleteEFElementCommand.DeleteInTransaction(cpc, entitySetToDelete);
            }

            // remove all properties from derived entity's key (it will inherit the base type's keys now)
            if (EntityToBeDerived.Key != null)
            {
                var propertyRefs = new List<PropertyRef>(EntityToBeDerived.Key.PropertyRefs);
                foreach (var propertyRef in propertyRefs)
                {
                    var property = propertyRef.Name.Target;
                    if (property != null)
                    {
                        var setKey = new SetKeyPropertyCommand(property, false, false, true);
                        CommandProcessor.InvokeSingleCommand(cpc, setKey);
                    }
                }
            }

            // set the base type
            EntityToBeDerived.BaseType.SetRefName(BaseType);

            //
            // if there is a referential constraint, then update any principals in the ref constraint to 
            // point to properties in the new entity type.
            //
            foreach (var end in EntityToBeDerived.GetAntiDependenciesOfType<AssociationEnd>())
            {
                foreach (var role in end.GetAntiDependenciesOfType<ReferentialConstraintRole>())
                {
                    var rc = role.Parent as ReferentialConstraint;
                    if (rc != null
                        && rc.Principal == role)
                    {
                        //
                        // this is the principal, so we want to update any keys in RC to reflect new keys 
                        // in the new base type.  If the number of keys don't match, we'll delete any leftovers
                        //
                        var keys = BaseType.ResolvableTopMostBaseType.ResolvableKeys.GetEnumerator();
                        foreach (var pr in rc.Principal.PropertyRefs)
                        {
                            if (keys.MoveNext())
                            {
                                // update this property ref to reflect the new key in the derived type
                                pr.Name.SetRefName(keys.Current);
                                ItemBinding[] bindings = { pr.Name };
                                CheckArtifactBindings.ScheduleBindingsForRebind(cpc, bindings);
                            }
                            else
                            {
                                // no more keys in the new base type, so delete this property ref & it's peer
                                // in the dependent section  
                                Command cmd = new DeleteReferentialConstraintPropertyRefCommand(pr);
                                // don't invoke this command now, as it will modify the collection we're iterating over
                                CommandProcessor.EnqueueCommand(cmd);
                            }
                        }
                    }
                }
            }

            // rebind and verify
            EntityToBeDerived.BaseType.Rebind();
            Debug.Assert(
                EntityToBeDerived.BaseType.Status == BindingStatus.Known,
                "EntityToBeDerived.BaseType.Status should be BindingStatus.Known, instead it is "
                + EntityToBeDerived.BaseType.Status.ToString());
        }
        protected override void InvokeInternal(CommandProcessorContext cpc)
        {
            // safety check, this should never be hit
            Debug.Assert(_derivedType != null, "InvokeInternal is called when DerivedType is null.");
            if (_derivedType == null)
            {
                throw new InvalidOperationException("InvokeInternal is called when DerivedType is null.");
            }

            // store off some local variables
            var baseType = _derivedType.BaseType.Target;
            var baseEntitySet = baseType.EntitySet as ConceptualEntitySet;
            var baseEntitySetMapping = (baseEntitySet == null ? null : baseEntitySet.EntitySetMapping);

            // save off a HashSet of all base types up the inheritance tree for searching later
            var allBaseTypes = new HashSet<EntityType>();
            for (var baseEntityType = baseType; baseEntityType != null; baseEntityType = baseEntityType.BaseType.Target)
            {
                allBaseTypes.Add(baseEntityType);
            }

            // set up list of all derived types down the inheritance tree
            var derivedAndAllDerivedTypes = new List<ConceptualEntityType>();
            derivedAndAllDerivedTypes.Add(_derivedType);
            derivedAndAllDerivedTypes.AddRange(_derivedType.ResolvableAllDerivedTypes);

            // remove any mappings which refer to properties which were inherited as these will
            // no longer be valid when the inheritance is deleted (and would cause the Mapping Details
            // window to open in non-edit mode). This must be done _before_ proceeding to clone the
            // EntityTypeMapping below and before we delete the inheritance (i.e. before the 
            // DefaultableValue Target becomes unresolved).
            var scalarPropsToDelete = new List<ScalarProperty>();
            if (allBaseTypes.Count > 0)
            {
                foreach (EntityType et in derivedAndAllDerivedTypes)
                {
                    foreach (var etm in et.GetAntiDependenciesOfType<EntityTypeMapping>())
                    {
                        foreach (var mf in etm.MappingFragments())
                        {
                            foreach (var sp in mf.AllScalarProperties())
                            {
                                var prop = sp.Name.Target;
                                if (prop != null)
                                {
                                    // find EntityType of which this Property is a member
                                    var propEntityType = prop.GetParentOfType(typeof(EntityType)) as EntityType;
                                    if (propEntityType != null
                                        && allBaseTypes.Contains(propEntityType))
                                    {
                                        // sp references a Property of an EntityType which will no longer
                                        // be in the inheritance hierarchy - so delete the mapping
                                        scalarPropsToDelete.Add(sp);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // cannot delete the ScalarProperty while enumerating over them - so instead delete in separate loop below
            foreach (var sp in scalarPropsToDelete)
            {
                DeleteEFElementCommand.DeleteInTransaction(cpc, sp);
            }

            // remove the inheritance
            _derivedType.BaseType.SetRefName(null);

            // re-resolve the derived type.  This will set the state of the _derivedType to be resolved (it could be unresolved because base-type binding could have been a duplicate or unknown binding). 
            _derivedType.State = EFElementState.Normalized;
            _derivedType.Resolve(_derivedType.Artifact.ArtifactSet);

            // the entity container we want to add it to
            var entityContainer = _derivedType.EntityModel.EntityContainer;
            Debug.Assert(entityContainer != null, "DerivedType does not have an Entity Container");

            // since this type no longer derives, it is stand alone and needs its own entity set
            // derive a name for the new entity set and create it
            var trialSetName = ModelHelper.ConstructProposedEntitySetName(_derivedType.Artifact, _derivedType.LocalName.Value);
            var ces = new CreateEntitySetCommand(trialSetName, _derivedType, true);
            CommandProcessor.InvokeSingleCommand(cpc, ces);
            var newEntitySet = ces.EntitySet as ConceptualEntitySet;

            // if the old entityset had mappings, then some may need to be moved
            if (baseEntitySetMapping != null)
            {
                // create a new EntitySetMapping for the new EntitySet that we made for the formally derivedType
                var createESM = new CreateEntitySetMappingCommand(entityContainer.EntityContainerMapping, newEntitySet);
                CommandProcessor.InvokeSingleCommand(cpc, createESM);
                var newEntitySetMapping = createESM.EntitySetMapping;

                // this type no longer derives from the type it used to, so its mappings can no longer
                // exist under the old EntitySetMapping, so we need to move them
                // move any EntityTypeMappings from the old EntitySetMapping used by the former base type
                // to the new one created for the new EntitySet and EntitySetMapping
                foreach (EntityType changingType in derivedAndAllDerivedTypes)
                {
                    var etms = new List<EntityTypeMapping>();
                    etms.AddRange(changingType.GetAntiDependenciesOfType<EntityTypeMapping>());

                    foreach (var etm in etms)
                    {
                        // here, to work around an xml editor bug, we clone the entity type mapping, instead of re-parenting it
                        var newetm = etm.Clone(newEntitySetMapping);

                        // now delete the old entity type mapping & dispose it. 
                        DeleteEFElementCommand.DeleteInTransaction(cpc, etm);
                    }
                }
            }

            //
            //  if there are any referential constraints properties whose principal ends refer to keys in the 
            //  old derived type, delete them
            //   
            foreach (var end in _derivedType.GetAntiDependenciesOfType<AssociationEnd>())
            {
                foreach (var role in end.GetAntiDependenciesOfType<ReferentialConstraintRole>())
                {
                    var rc = role.Parent as ReferentialConstraint;
                    if (rc != null
                        && rc.Principal == role)
                    {
                        foreach (var pr in rc.Principal.PropertyRefs)
                        {
                            Command cmd = new DeleteReferentialConstraintPropertyRefCommand(pr);
                            // don't invoke this command now, as it will modify the collection we're iterating over
                            CommandProcessor.EnqueueCommand(cmd);
                        }
                    }
                }
            }
        }
        protected override void InvokeInternal(CommandProcessorContext cpc)
        {
            // make sure that there isn't an ETM of this kind already
            var entityTypeMapping = ModelHelper.FindEntityTypeMapping(cpc, _entityType, _kind, false);
            Debug.Assert(entityTypeMapping == null, "We are calling CreateEntityTypeMappingCommand and there is already one of this Kind");
            if (entityTypeMapping != null)
            {
                _created = entityTypeMapping;
                return;
            }

            // see if we can get the EntitySetMapping for our entity (if we weren't passed it)
            if (_entitySetMapping == null)
            {
                var ces = _entityType.EntitySet as ConceptualEntitySet;
                Debug.Assert(ces != null, "_entityType.EntitySet should be a ConceptualEntitySet");

                // find the EntitySetMapping for this type (V1 assumption is that there is only ESM per ES)
                EntitySetMapping esm = null;
                foreach (var depMapping in ces.GetAntiDependenciesOfType<EntitySetMapping>())
                {
                    esm = depMapping;
                    break;
                }

                _entitySetMapping = esm;
            }

            // if we still don't have an ESM, create one
            if (_entitySetMapping == null)
            {
                var cmd = new CreateEntitySetMappingCommand(
                    _entityType.Artifact.MappingModel().FirstEntityContainerMapping,
                    _entityType.EntitySet as ConceptualEntitySet);
                CommandProcessor.InvokeSingleCommand(cpc, cmd);
                _entitySetMapping = cmd.EntitySetMapping;
            }
            Debug.Assert(
                _entitySetMapping != null,
                "_entitySetMapping should not be null - we have been unable to find or create an EntitySetMapping");

            // create the ETM
            var etm = new EntityTypeMapping(_entitySetMapping, null, _kind);
            etm.TypeName.SetRefName(_entityType);
            _entitySetMapping.AddEntityTypeMapping(etm);

            XmlModelHelper.NormalizeAndResolve(etm);

            _created = etm;
        }
        /// <summary>
        ///     Creates a new EntitySetMapping in the existing EntityContainerMapping
        ///     based on another EntitySetMapping (esmToClone) in a different artifact.
        ///     Uses the FindMatchingEntityTypeInExistingArtifact() to match EntityTypes
        ///     within the EntitySetMapping.
        /// </summary>
        private EntitySetMapping CloneEntitySetMapping(
            CommandProcessorContext cpc, EntitySetMapping esmToClone,
            EntityContainerMapping existingEntityContainerMapping, ConceptualEntitySet existingEntitySet,
            Dictionary<EntityType, EntityType> tempArtifactCEntityTypeToNewCEntityTypeInExistingArtifact)
        {
            var createESM = new CreateEntitySetMappingCommand(existingEntityContainerMapping, existingEntitySet);
            CommandProcessor.InvokeSingleCommand(cpc, createESM);
            var esm = createESM.EntitySetMapping;

            foreach (var etmToBeCloned in esmToClone.EntityTypeMappings())
            {
                var bindings = etmToBeCloned.TypeName.Bindings;
                if (bindings.Count != 1)
                {
                    Debug.Fail(
                        "EntityTypeMapping to be cloned " + etmToBeCloned.ToPrettyString() +
                        " has bindings count = " + bindings.Count + ". We only support 1 binding.");
                }
                else
                {
                    var b = bindings.First();
                    var etToBeCloned = b.Target as ConceptualEntityType;
                    Debug.Assert(etToBeCloned != null, "EntityType target of binding is not ConceptualEntityType");
                    var etInExistingArtifact =
                        FindMatchingConceptualEntityTypeInExistingArtifact(
                            etToBeCloned,
                            tempArtifactCEntityTypeToNewCEntityTypeInExistingArtifact);
                    if (null != etInExistingArtifact)
                    {
                        CreateEntityTypeMappingCommand.CloneEntityTypeMapping(
                            cpc,
                            etmToBeCloned,
                            esm,
                            etInExistingArtifact,
                            etmToBeCloned.Kind);
                    }
                    else
                    {
                        throw new UpdateModelFromDatabaseException(
                            string.Format(
                                CultureInfo.CurrentCulture,
                                Resources.UpdateFromDatabaseEntitySetMappingCannotFindEntityType,
                                etToBeCloned.ToPrettyString()));
                    }
                }
            }

            return esm;
        }