protected override void InvokeInternal(CommandProcessorContext cpc) { if (!string.IsNullOrEmpty(Role) && !string.Equals(End.Role.Value, Role, StringComparison.Ordinal)) { // TODO: should this command be enqueued in the command processor? RenameCommand c = new EntityDesignRenameCommand(End, Role, true); CommandProcessor.InvokeSingleCommand(cpc, c); // bug 563525: we need to update EndProperties within AssociationSetMappings if the AssociationEnd changes. // we update the "Role" of an AssociationSetEnd in the RenameCommand but the SingleItemBinding that we have to update // that is bound to the AssociationSetEnd is unique to this situation; it is not technically a "refactor rename". var associationSetEnd = End.GetAntiDependenciesOfType <AssociationSetEnd>().FirstOrDefault(); if (associationSetEnd != null) { // we need to renormalize the associationSetEnd, since the role name will have changed. XmlModelHelper.NormalizeAndResolve(associationSetEnd); var endPropertiesInAssocSetMappings = associationSetEnd.GetAntiDependenciesOfType <EndProperty>(); foreach (var endProperty in endPropertiesInAssocSetMappings) { endProperty.Name.SetRefName(associationSetEnd); CheckArtifactBindings.ScheduleBindingsForRebind(cpc, new HashSet <ItemBinding> { endProperty.Name }); } } } }
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()); }