protected override void InvokeInternal(CommandProcessorContext cpc) { Debug.Assert(cpc != null, "InvokeInternal is called when EntityContainerMapping is null."); // safety check, this should never be hit if (EntityType == null) { throw new InvalidOperationException("InvokeInternal is called when entity type is null"); } EntityType.Abstract.Value = SetAbstract; // remove any function mappings if we are setting this to abstract if (SetAbstract) { var etms = new List <EntityTypeMapping>(); etms.AddRange(EntityType.GetAntiDependenciesOfType <EntityTypeMapping>()); for (var i = etms.Count - 1; i >= 0; i--) { var etm = etms[i]; if (etm != null && etm.Kind == EntityTypeMappingKind.Function) { DeleteEFElementCommand.DeleteInTransaction(cpc, etm); } } } XmlModelHelper.NormalizeAndResolve(EntityType); }
protected override void InvokeInternal(CommandProcessorContext cpc) { if (String.IsNullOrEmpty(_longDescriptionText)) { if (_efElement.Documentation != null && _efElement.Documentation.LongDescription != null) { DeleteEFElementCommand.DeleteInTransaction(cpc, _efElement.Documentation.LongDescription); // if the documentation node is empty, delete it if (_efElement.Documentation.Summary == null) { DeleteEFElementCommand.DeleteInTransaction(cpc, _efElement.Documentation); } } } else { if (_efElement.Documentation == null) { _efElement.Documentation = new Documentation(_efElement, null); } if (_efElement.Documentation.LongDescription == null) { _efElement.Documentation.LongDescription = new LongDescription(_efElement.Documentation, null); } _efElement.Documentation.LongDescription.Text = _longDescriptionText; XmlModelHelper.NormalizeAndResolve(_efElement); } }
private static void ReplaceModelRoot( CommandProcessorContext cpc, EFRuntimeModelRoot existingModelRoot, XmlReader newSchemaReader, CreateModelRootCallback createModelRootCallback) { var newModelRootNode = XElement.Load(newSchemaReader); // find the XObject representing the existing EFRuntimeModelRoot EFObject var existingModelRootNode = existingModelRoot.XObject as XElement; Debug.Assert(existingModelRootNode != null, "existingRootXElement is null in ReplaceModelRoot()"); // find the parent of the existing XObject tied to the EFRuntimeModelRoot var existingModelRootParentNode = existingModelRootNode.Parent; // delete the old EFRuntimeModelRoot EFObject but do not delete its anti-dependencies if (null != existingModelRoot) { var deleteConceptualModelCommand = new DeleteEFElementCommand(existingModelRoot, true, false); DeleteEFElementCommand.DeleteInTransaction(cpc, deleteConceptualModelCommand); } existingModelRootParentNode.Add(newModelRootNode); // Callback to create the EFRuntimeModelRoot EFObject createModelRootCallback(newModelRootNode); }
private static void DeleteAllParameters(CommandProcessorContext cpc, FunctionImport fi) { IList <Parameter> parametersToDelete = new List <Parameter>(); foreach (var parameter in fi.Parameters()) { parametersToDelete.Add(parameter); } foreach (var parameter in parametersToDelete) { DeleteEFElementCommand.DeleteInTransaction(cpc, parameter); } }
private static void DeleteMappingsForFunctions(CommandProcessorContext cpc, HashSet <Function> functions) { if (null != functions) { foreach (var f in functions) { foreach (var fim in f.GetAntiDependenciesOfType <FunctionImportMapping>()) { DeleteEFElementCommand.DeleteInTransaction(cpc, fim); } } } }
protected override void PreInvoke(CommandProcessorContext cpc) { base.PreInvoke(cpc); // first make sure that we are changing the type if (_property != null && _property.ComplexType.Target != _newType) { foreach (var cp in _property.GetAntiDependenciesOfType <ComplexProperty>()) { // delete all related ComplexProperty mappings when the property type changes DeleteEFElementCommand.DeleteInTransaction(cpc, cp); } } }
protected override void PostInvoke(CommandProcessorContext cpc) { // now that we have a new entity set, make sure that it and any derived types use correct MSL EnforceEntitySetMappingRules.AddRule(cpc, _derivedType.EntitySet); // see if this type is used by association ends; since we deleted the inheritance, this entity got // a new EntitySet so we need to change any EntitySet references for corresponding AssociationSetEnds to the new one Association association = null; foreach (var end in _derivedType.GetAntiDependenciesOfType <AssociationEnd>()) { foreach (var setEnd in end.GetAntiDependenciesOfType <AssociationSetEnd>()) { setEnd.EntitySet.SetRefName(_derivedType.EntitySet); XmlModelHelper.NormalizeAndResolve(setEnd); } association = end.Parent as Association; } // try to recreate the AssociationSetMapping if one exists if (association != null && association.AssociationSet != null && association.AssociationSet.AssociationSetMapping != null && association.AssociationSet.AssociationSetMapping.XObject != null) { // store off the entity set for later var storeEntitySet = association.AssociationSet.AssociationSetMapping.StoreEntitySet.Target; // delete it DeleteEFElementCommand.DeleteInTransaction(cpc, association.AssociationSet.AssociationSetMapping); // create a new one (if we can) if (storeEntitySet != null && storeEntitySet.EntityType.Target != null) { var set = storeEntitySet.EntityType.Target as StorageEntityType; Debug.Assert(storeEntitySet.EntityType.Target == null || set != null, "EntityType is not StorageEntityType"); CreateAssociationSetMappingCommand.CreateAssociationSetMappingAndIntellimatch(cpc, association, set); } } base.PostInvoke(cpc); }
protected override void PostInvoke(CommandProcessorContext cpc) { foreach (var property in _properties) { var deleteCommand = property.GetDeleteCommand(); var deletePropertyCommand = deleteCommand as DeletePropertyCommand; Debug.Assert( deletePropertyCommand != null, "Property.GetDeleteCommand() failed to return a DeletePropertyCommand, command translation will not receive the correct value for the IsConceptualDeleteOnly flag"); if (deletePropertyCommand != null) { deletePropertyCommand.IsConceptualOnlyDelete = true; } DeleteEFElementCommand.DeleteInTransaction(cpc, deletePropertyCommand); } }
private static void DeleteMappingsForEntitySets(CommandProcessorContext cpc, HashSet <StorageEntitySet> storageEntitySets) { if (null != storageEntitySets) { foreach (var ses in storageEntitySets) { foreach (var mappingFragment in ses.GetAntiDependenciesOfType <MappingFragment>()) { DeleteEFElementCommand.DeleteInTransaction(cpc, mappingFragment); } foreach (var asm in ses.GetAntiDependenciesOfType <AssociationSetMapping>()) { DeleteEFElementCommand.DeleteInTransaction(cpc, asm); } } } }
/// <summary> /// We override this method to do some specialized processing of removing connectors associated with the shape. /// </summary> /// <param name="cpc"></param> protected override void RemoveAntiDeps(CommandProcessorContext cpc) { var associationConnectors = ModelHelper.GetListOfAssociationConnectorsForEntityTypeShape(EntityTypeShape).ToArray(); foreach (var associationConnector in associationConnectors) { DeleteEFElementCommand.DeleteInTransaction(cpc, associationConnector); } var inheritanceConnectors = ModelHelper.GetListOfInheritanceConnectorsForEntityTypeShape(EntityTypeShape).ToArray(); foreach (var inheritanceConnector in inheritanceConnectors) { DeleteEFElementCommand.DeleteInTransaction(cpc, inheritanceConnector); } // process the remaining antiDeps normally base.RemoveAntiDeps(cpc); }
/// <summary> /// Update the underlying function/store-procedure if they are changed. /// </summary> private void UpdateFunctionImportFunction(CommandProcessorContext cpc) { if (Function != FunctionImport.Function) { // if the user selected "(None)" then delete the FunctionImportMapping if (Function == null) { DeleteEFElementCommand.DeleteInTransaction(cpc, FunctionImport.FunctionImportMapping); } // if the user selected another stored procedure, update the mapping // and the parameters of the function import else { var functionImportMapping = FunctionImport.FunctionImportMapping; if (functionImportMapping == null) { // if there isn't a FunctionImportMapping already, we need to create it with the FunctionName if (FunctionImport.Artifact != null && FunctionImport.Artifact.MappingModel() != null && FunctionImport.Artifact.MappingModel().FirstEntityContainerMapping != null) { var cmdFuncImpMapping = new CreateFunctionImportMappingCommand( FunctionImport.Artifact.MappingModel().FirstEntityContainerMapping, Function, FunctionImport); CommandProcessor.InvokeSingleCommand(cpc, cmdFuncImpMapping); } } else { // update the FunctionName in the FunctionImportMapping functionImportMapping.FunctionName.SetRefName(Function); AddToBeNormalizedEFContainerItem(functionImportMapping); } } // finally, update the parameters of the function import to match the function CreateFunctionImportCommand.UpdateFunctionImportParameters(cpc, FunctionImport, Function); } }
protected override void InvokeInternal(CommandProcessorContext cpc) { // recycle connectors to avoid having rebinding the model var connectorPoints = new List <ConnectorPoint>(_connector.ConnectorPoints); if (connectorPoints.Count > _edgePoints.Count) { var diff = _connector.ConnectorPoints.Count - _edgePoints.Count; for (var i = 0; i < diff; i++) { var lastIdx = connectorPoints.Count - 1; var cp = connectorPoints[lastIdx]; DeleteEFElementCommand.DeleteInTransaction(cpc, cp); connectorPoints.RemoveAt(lastIdx); } } else if (connectorPoints.Count < _edgePoints.Count) { var diff = _edgePoints.Count - connectorPoints.Count; for (var i = 0; i < diff; i++) { var cp = new ConnectorPoint(_connector, null); _connector.AddConnectorPoint(cp); XmlModelHelper.NormalizeAndResolve(cp); connectorPoints.Add(cp); } } Debug.Assert(connectorPoints.Count == _edgePoints.Count, "ConnectorPoints.Count != edgePoints.Count"); // be safe if the assert above fires, only go through min indices var min = Math.Min(_edgePoints.Count, connectorPoints.Count); for (var i = 0; i < min; i++) { var edgePoint = _edgePoints[i]; var connectorPoint = connectorPoints[i]; connectorPoint.PointX.Value = edgePoint.Key; connectorPoint.PointY.Value = edgePoint.Value; } }
protected override void InvokeInternal(CommandProcessorContext cpc) { Debug.Assert(null != _entitySets, "Null entitySets in DeleteUnmappedStorageEntitySetsCommand.InvokeInternal()"); if (null == _entitySets) { return; } // loop over the unmapped StorageEntitySets deleting them, also create // a list of any StorageEntityTypes referenced by these StorageEntitySets // Note: have to convert to array first to prevent exceptions due to // editing the collection while iterating over it var entitySets = _entitySets.ToArray(); var entityTypesList = new List <StorageEntityType>(); foreach (var entitySet in entitySets) { // find any EntityType which is referenced by this EntitySet if (null != entitySet.EntityType && null != entitySet.EntityType.Target) { var et = entitySet.EntityType.Target as StorageEntityType; if (null != et) { entityTypesList.Add(et); } } DeleteEFElementCommand.DeleteInTransaction(cpc, entitySet); } // delete all StorageEntityTypes found above var entityTypes = entityTypesList.ToArray(); foreach (var entityType in entityTypes) { DeleteEFElementCommand.DeleteInTransaction(cpc, entityType); } }
private static void ReplaceSsdl(CommandProcessorContext cpc, EntityDesignArtifact existingArtifact, XElement newSsdl) { // find the XObject representing the existing StorageModel Schema element var existingStorageModelNode = existingArtifact.StorageModel.XObject as XElement; Debug.Assert(existingStorageModelNode != null, "existingStorageModelNode is null"); // find the parent of the existing StorageModel Schema element var existingStorageModelParentNode = existingStorageModelNode.Parent; // delete the old StorageModel but do not delete its anti-dependencies if (null != existingArtifact.StorageModel) { var deleteStorageModelCommand = new DeleteEFElementCommand(existingArtifact.StorageModel, true, false); DeleteEFElementCommand.DeleteInTransaction(cpc, deleteStorageModelCommand); } // this will clone the source element var ssdlSchemaElement = new XElement(newSsdl); // add ssdlSchemaElement to the parent of the previously existing Storage node existingStorageModelParentNode.Add(ssdlSchemaElement); // create a new StorageModel object, add it back into the artifact and re-parse existingArtifact.StorageModel = new StorageEntityModel(existingArtifact, ssdlSchemaElement); existingArtifact.StorageModel.Parse(new HashSet <XName>()); Debug.Assert( EFElementState.Parsed == existingArtifact.StorageModel.State, "StorageModel State should be Parsed, instead it is " + existingArtifact.StorageModel.State); // normalize and resolve the StorageModel XmlModelHelper.NormalizeAndResolve(existingArtifact.StorageModel); Debug.Assert( EFElementState.Resolved == existingArtifact.StorageModel.State, "StorageModel State should be Resolved, instead it is " + existingArtifact.StorageModel.State); }
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(Property != null, "InvokeInternal is called when property is null."); if (Property == null) { throw new InvalidOperationException("InvokeInternal is called when Property is null."); } if (Property.IsKeyProperty == IsKey) { // no change needed return; } if (IsKey) { if (Property.EntityType.Key == null) { Property.EntityType.Key = new Key(Property.EntityType, null); } // make the key property non-nullable Property.Nullable.Value = BoolOrNone.FalseValue; Property.EntityType.Key.AddPropertyRef(Property); // normalize & resolve the key property XmlModelHelper.NormalizeAndResolve(Property.EntityType.Key); } else { var keyElement = Property.EntityType.Key; Debug.Assert(keyElement != null, "keyElement should not be null"); if (keyElement != null) { keyElement.RemovePropertyRef(Property); if (!keyElement.Children.Any()) { keyElement.Delete(); } else { XmlModelHelper.NormalizeAndResolve(keyElement); } } // if we are changing from key to non-key and this key is referenced by a principal end of // a ref constraint, then we want to delete that entry in the ref constraint if (IsKey == false && _deletePrincipalRCRefs) { foreach (var pref in Property.GetAntiDependenciesOfType <PropertyRef>()) { if (pref != null) { var role = pref.Parent as ReferentialConstraintRole; if (role != null) { var rc = role.Parent as ReferentialConstraint; if (rc != null && rc.Principal == role) { // property ref on a principal end, so delete it DeleteEFElementCommand.DeleteInTransaction(cpc, pref); } } } } } } var cet = Property.EntityType as ConceptualEntityType; if (cet != null) { PropagateViewKeysToStorageModel.AddRule(cpc, cet); } }
/// <summary> /// Update function import return type if requested. /// </summary> private void UpdateFunctionImportReturnType(CommandProcessorContext cpc) { if (ChangeReturnType) { // figure out if we are using a complex type, an entity type, primitive type or none as the return type var complexType = ReturnSingleType as ComplexType; var entityType = ReturnSingleType as EntityType; // if returnTypeStringValue is not null, the value could be "None" or the string representation of primitive types (for example: "string", "Int16"). var returnTypeStringValue = ReturnSingleType as string; // Only delete type-mapping if the function-import's return-type does not match type-mapping's type. var functionImportMapping = FunctionImport.FunctionImportMapping; if (functionImportMapping != null && functionImportMapping.ResultMapping != null) { foreach (var typeMapping in functionImportMapping.ResultMapping.TypeMappings().ToList()) { // If the old type mapping is FunctionImportComplexTypeMapping and function import does not return a complex type // or return a different complex type. if (typeMapping is FunctionImportComplexTypeMapping && (complexType == null || !String.Equals(typeMapping.TypeName.Target.DisplayName, complexType.DisplayName, StringComparison.CurrentCulture))) { DeleteEFElementCommand.DeleteInTransaction(cpc, typeMapping); } // If the old type mapping is FunctionImportEntityTypeMapping and function import does not return an entity type // or return a different entity type. else if (typeMapping is FunctionImportEntityTypeMapping && (entityType == null || !String.Equals(typeMapping.TypeName.Target.DisplayName, entityType.DisplayName, StringComparison.CurrentCulture))) { DeleteEFElementCommand.DeleteInTransaction(cpc, typeMapping); } } // If ResultMapping does not contain any type mappings, delete it. if (functionImportMapping.ResultMapping.TypeMappings().Count == 0) { DeleteEFElementCommand.DeleteInTransaction(cpc, functionImportMapping.ResultMapping); } } // we won't do any equality checking here against the original function import's return type // because we would expend cycles determining the 'collection' string, etc. string updatedReturnTypeAsString = null; if (entityType != null) { // Return type could be a collection of EntityType, ComplexType or primitive type. // If we change from the return type from a complex type to an entity type, we need to remove the complex type binding in the function import. // Check if complex type binding is not null and reset it. if (FunctionImport.ReturnTypeAsComplexType != null) { FunctionImport.ReturnTypeAsComplexType.SetRefName(null); FunctionImport.ReturnTypeAsComplexType.Rebind(); } // if we are using an entity type, the return type is "Collection(entityType)" Debug.Assert(entityType.EntitySet != null, "Entity Type doesn't have an Entity Set we can use for the Function Import"); if (entityType.EntitySet != null) { FunctionImport.EntitySet.SetRefName(entityType.EntitySet); FunctionImport.EntitySet.Rebind(); FunctionImport.ReturnTypeAsEntityType.SetRefName(entityType); FunctionImport.ReturnTypeAsEntityType.Rebind(); } } else if (complexType != null) { // if we change from an entity type to any other type, we need to remove the EntitySet binding on the FunctionImport if (FunctionImport.EntitySet.RefName != null) { FunctionImport.EntitySet.SetRefName(null); FunctionImport.EntitySet.Rebind(); } FunctionImport.ReturnTypeAsComplexType.SetRefName(complexType); FunctionImport.ReturnTypeAsComplexType.Rebind(); } else { // Return type could be a collection of EntityType, ComplexType or primitive type. // If we change from the return type from a complex type to a primitive type, we need to remove the complex type binding in the function import. // Check if complex type binding is not null and reset it. if (FunctionImport.ReturnTypeAsComplexType != null) { FunctionImport.ReturnTypeAsComplexType.SetRefName(null); FunctionImport.ReturnTypeAsComplexType.Rebind(); } // if we change from an entity type to any other type, we need to remove the EntitySet binding on the FunctionImport if (FunctionImport.EntitySet.RefName != null) { FunctionImport.EntitySet.SetRefName(null); FunctionImport.EntitySet.Rebind(); } // if the new value is 'None' then set the return type to null if (returnTypeStringValue != Tools.XmlDesignerBase.Resources.NoneDisplayValueUsedForUX) { updatedReturnTypeAsString = String.Format( CultureInfo.InvariantCulture, FunctionImport.CollectionFormat, returnTypeStringValue); } // update the actual return type of the function import FunctionImport.ReturnTypeAsPrimitiveType.Value = updatedReturnTypeAsString; } } }
protected override void PreInvoke(CommandProcessorContext cpc) { base.PreInvoke(cpc); // you cannot use this command with a type that already has a base class; throwing here // because its not a good idea to throw an exception in a c'tor if (EntityToBeDerived == null || EntityToBeDerived.BaseType.Target != null) { throw new InvalidOperationException(); } EnforceEntitySetMappingRules.AddRule(cpc, BaseType.EntitySet); // see if this type is used by association ends; since we are creating an inheritance // we need to change any AssociationSetEnd references from the current EntitySet to the // new baseType's EntitySet (the derived type's EntitySet will be deleted) var associationsToUpdate = new HashSet <Association>(); if (EntityToBeDerived.EntitySet != null) { var associationSetEndsToUpdate = EntityToBeDerived.EntitySet.GetAntiDependenciesOfType <AssociationSetEnd>(); foreach (var setEnd in associationSetEndsToUpdate) { setEnd.EntitySet.SetRefName(BaseType.EntitySet); XmlModelHelper.NormalizeAndResolve(setEnd); var aSet = setEnd.Parent as AssociationSet; if (aSet != null) { if (aSet.Association.Target != null) { associationsToUpdate.Add(aSet.Association.Target); } } } } foreach (var association in associationsToUpdate) { // try to recreate the AssociationSetMapping if one exists if (association != null && association.AssociationSet != null && association.AssociationSet.AssociationSetMapping != null && association.AssociationSet.AssociationSetMapping.XObject != null) { // store off the entity set for later var storeEntitySet = association.AssociationSet.AssociationSetMapping.StoreEntitySet.Target; // delete it DeleteEFElementCommand.DeleteInTransaction(cpc, association.AssociationSet.AssociationSetMapping); // create a new one (if we can) if (storeEntitySet != null && storeEntitySet.EntityType.Target != null) { var set = storeEntitySet.EntityType.Target as StorageEntityType; Debug.Assert(set != null, "EntityType is not StorageEntityType"); CreateAssociationSetMappingCommand.CreateAssociationSetMappingAndIntellimatch(cpc, association, set); } } } }
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()); }
/// <summary> /// If this element has any children that have unresolved references /// or has itself an unresolved reference then Delete the element /// NB: Be warned this method is destructive. If you have unbound /// elements for whatever reason then those elements will be removed. /// </summary> private static void RecursiveDeleteUnboundElements(CommandProcessorContext cpc, EFElement efElement) { var mappingCondition = efElement as Condition; var queryView = efElement as QueryView; if (mappingCondition != null) { // A Mapping Condition is special because it will // only ever have 1 bound child out of 2 var children = efElement.Children.ToArray(); var anyOneOfChildrenIsBound = children.OfType <ItemBinding>().Any(itemBinding => itemBinding.Resolved); if (!anyOneOfChildrenIsBound) { DeleteEFElementCommand.DeleteInTransaction(cpc, efElement); } return; } else if (queryView != null) { // QueryView elements have a TypeName attribute, but it is optional and // so the QueryView should not be deleted even if the TypeName attribute // is not in a Resolved state return; } else { // cannot use IEnumerable directly as we are potentially // deleting from the returned collection var children = new List <EFObject>(efElement.Children); // remove any children which are optional (and hence not being resolved does not require a delete) var cp = efElement as ComplexProperty; if (cp != null) { // TypeName binding in ComplexProperty is optional and can be unresolved, so remove it from the check list children.Remove(cp.TypeName); } var mf = efElement as ModificationFunction; if (mf != null) { children.Remove(mf.RowsAffectedParameter); } // loop over children and recursively delete foreach (var child in children) { var efElementChild = child as EFElement; var itemBindingChild = child as ItemBinding; if (efElementChild != null) { RecursiveDeleteUnboundElements(cpc, efElementChild); } else if (itemBindingChild != null) { if (!itemBindingChild.Resolved) { DeleteEFElementCommand.DeleteInTransaction(cpc, efElement); return; } } } } }