public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) { if (context == null || context.Instance == null) { return value; } var desc = context.Instance as EFAssociationDescriptor; if (desc != null) { var assoc = desc.WrappedItem as Association; if (assoc != null) { var commands = ReferentialConstraintDialog.LaunchReferentialConstraintDialog(assoc); var cpc = new CommandProcessorContext( desc.EditingContext, EfiTransactionOriginator.PropertyWindowOriginatorId, Resources.Tx_ReferentialContraint); var cp = new CommandProcessor(cpc); foreach (var c in commands) { cp.EnqueueCommand(c); } cp.Invoke(); } } return value; }
/// <summary> /// This helper function will create a Diagram using default name. /// NOTE: If the cpc already has an active transaction, these changes will be in that transaction /// and the caller of this helper method must commit it to see these changes commited /// otherwise the diagram will never be created. /// </summary> /// <param name="cpc"></param> /// <returns>The new ComplexType</returns> internal static Diagram CreateDiagramWithDefaultName(CommandProcessorContext cpc) { Debug.Assert(cpc != null, "The passed in CommandProcessorContext is null."); if (cpc != null) { var service = cpc.EditingContext.GetEFArtifactService(); var entityDesignArtifact = service.Artifact as EntityDesignArtifact; if (entityDesignArtifact == null || entityDesignArtifact.DesignerInfo == null || entityDesignArtifact.DesignerInfo.Diagrams == null) { throw new CannotLocateParentItemException(); } var diagramName = ModelHelper.GetUniqueNameWithNumber( typeof(Diagram), entityDesignArtifact.DesignerInfo.Diagrams, Resources.Model_DefaultDiagramName); // go create it var cp = new CommandProcessor(cpc); var cmd = new CreateDiagramCommand(diagramName, entityDesignArtifact.DesignerInfo.Diagrams); cp.EnqueueCommand(cmd); cp.Invoke(); return cmd.Diagram; } return null; }
internal static void StaticInvoke(CommandProcessorContext cpc, EntityTypeShape entityTypeShape, Guid domainPropertyId) { var viewModel = entityTypeShape.GetRootViewModel(); Debug.Assert(viewModel != null, "Unable to find root view model from entity type shape:" + entityTypeShape.AccessibleName); if (viewModel != null) { var modelEntityShape = viewModel.ModelXRef.GetExisting(entityTypeShape) as Model.Designer.EntityTypeShape; // If ModelXRef does not contain about model EntityTypeShape,try to get the information through DSL Model Element if (modelEntityShape == null) { var modelDiagram = viewModel.ModelXRef.GetExisting(viewModel.GetDiagram()) as Diagram; var entityType = viewModel.ModelXRef.GetExisting(entityTypeShape.ModelElement) as EntityType; Debug.Assert(modelDiagram != null, "Why Escher Diagram is null?"); Debug.Assert(entityType != null, "Why there is no XRef between Escher EntityType and DSL EntityT?"); if (modelDiagram != null && entityType != null) { modelEntityShape = entityType.GetAntiDependenciesOfType<Model.Designer.EntityTypeShape>() .FirstOrDefault(ets => ets.Diagram.Id == modelDiagram.Id.Value); } if (modelEntityShape != null) { viewModel.ModelXRef.Add(modelEntityShape, entityTypeShape, cpc.EditingContext); } } // if modelentityshape is still null, create one if (modelEntityShape == null) { EntityTypeShapeAdd.StaticInvoke(cpc, entityTypeShape); modelEntityShape = viewModel.ModelXRef.GetExisting(entityTypeShape) as Model.Designer.EntityTypeShape; } Debug.Assert(modelEntityShape != null); if (modelEntityShape != null) { if (domainPropertyId == NodeShape.AbsoluteBoundsDomainPropertyId) { var cp = new CommandProcessor(cpc); cp.EnqueueCommand( new UpdateDefaultableValueCommand<double>(modelEntityShape.PointX, entityTypeShape.AbsoluteBounds.X)); cp.EnqueueCommand( new UpdateDefaultableValueCommand<double>(modelEntityShape.PointY, entityTypeShape.AbsoluteBounds.Y)); cp.EnqueueCommand( new UpdateDefaultableValueCommand<double>(modelEntityShape.Width, entityTypeShape.AbsoluteBounds.Width)); cp.Invoke(); } else if (domainPropertyId == NodeShape.IsExpandedDomainPropertyId) { var cmd = new UpdateDefaultableValueCommand<bool>(modelEntityShape.IsExpanded, entityTypeShape.IsExpanded); CommandProcessor.InvokeSingleCommand(cpc, cmd); } } } }
protected override void InvokeInternal(CommandProcessorContext cpc) { // first create new ComplexType _createdComplexType = CreateComplexTypeCommand.CreateComplexTypeWithDefaultName(cpc); // add a copy of Entity properties to the ComplexType var copyCmd = new CopyPropertiesCommand(new PropertiesClipboardFormat(_properties), _createdComplexType); var propertyName = ModelHelper.GetUniqueConceptualPropertyName( ComplexConceptualProperty.DefaultComplexPropertyName, _entityType); // add a new Property of created ComplexType to the Entity var createCPCmd = new CreateComplexPropertyCommand(propertyName, _entityType, _createdComplexType); var cp = new CommandProcessor(cpc, copyCmd, createCPCmd); cp.Invoke(); _createdComplexProperty = createCPCmd.Property; // preserve mappings foreach (var property in _properties) { if (property is ComplexConceptualProperty) { var createdComplexTypeProperty = _createdComplexType.FindPropertyByLocalName(property.LocalName.Value) as ComplexConceptualProperty; Debug.Assert(createdComplexTypeProperty != null, "Copied complex property not found"); if (createdComplexTypeProperty != null) { foreach (var complexPropertyMapping in property.GetAntiDependenciesOfType<ComplexProperty>()) { PreserveComplexPropertyMapping(cpc, complexPropertyMapping, createdComplexTypeProperty); } foreach (var fcp in property.GetAntiDependenciesOfType<FunctionComplexProperty>()) { PreserveFunctionComplexPropertyMapping(cpc, fcp, createdComplexTypeProperty); } } } else { var createdComplexTypeProperty = _createdComplexType.FindPropertyByLocalName(property.LocalName.Value); Debug.Assert(createdComplexTypeProperty != null, "Copied property not found"); if (createdComplexTypeProperty != null) { // update EntityTypeMappings foreach (var scalarPropertyMapping in property.GetAntiDependenciesOfType<ScalarProperty>()) { PreserveScalarPropertyMapping(cpc, scalarPropertyMapping, createdComplexTypeProperty); } // update ModificationFunctionMappings foreach (var fsp in property.GetAntiDependenciesOfType<FunctionScalarProperty>()) { PreserveFunctionScalarPropertyMapping(cpc, fsp, createdComplexTypeProperty); } } } } }
internal override void Invoke(CommandProcessorContext cpc) { var viewModel = _entityType.GetRootViewModel(); Debug.Assert(viewModel != null, "Unable to find root view model from entity type: " + _entityType.Name); if (viewModel != null) { var entityType = viewModel.ModelXRef.GetExisting(_entityType) as Model.Entity.EntityType; Debug.Assert(entityType != null); Command c = new EntityDesignRenameCommand(entityType, _entityType.Name, true); var cp = new CommandProcessor(cpc, c); cp.Invoke(); } }
internal override void Invoke(CommandProcessorContext cpc) { var viewModel = _property.GetRootViewModel(); Debug.Assert(viewModel != null, "Unable to find root view model from property: " + _property.Name); if (viewModel != null) { var property = viewModel.ModelXRef.GetExisting(_property) as Model.Entity.Property; Debug.Assert(property != null); Command c = new EntityDesignRenameCommand(property, _property.Name, true); var cp = new CommandProcessor(cpc, c); cp.Invoke(); } }
internal static NavigationProperty CreateDefaultProperty(CommandProcessorContext cpc, string name, ConceptualEntityType entity) { if (cpc == null) { throw new ArgumentNullException("cpc"); } if (string.IsNullOrEmpty(name)) { throw new ArgumentNullException("name"); } if (entity == null) { throw new ArgumentNullException("entity"); } var cpcd = new CreateNavigationPropertyCommand(name, entity, null, null, null); var cp = new CommandProcessor(cpc, cpcd); cp.Invoke(); return cpcd.NavigationProperty; }
internal static bool SetBaseEntityType( CommandProcessorContext cpc, ConceptualEntityType derivedEntity, ConceptualEntityType baseEntity) { if (ModelHelper.CheckForCircularInheritance(derivedEntity, baseEntity)) { var message = String.Format( CultureInfo.CurrentCulture, Resources.Error_CircularInheritanceAborted, derivedEntity.LocalName.Value, baseEntity.LocalName.Value); VsUtils.ShowErrorDialog(message); return false; } var cp = new CommandProcessor(cpc); if (derivedEntity.BaseType.Target != null) { // CreateInheritanceCommand works only for entities that don't have base type set // so we need to remove base type first in this case cp.EnqueueCommand(new DeleteInheritanceCommand(derivedEntity)); } if (baseEntity != null) { // in case the user has chosen "(None)" then we just want to delete the existing one cp.EnqueueCommand(new CreateInheritanceCommand(derivedEntity, baseEntity)); } // a quick check to be sure Debug.Assert(cp.CommandCount > 0, "Why didn't we enqueue at least one command?"); if (cp.CommandCount > 0) { cp.Invoke(); } return true; }
internal void CreateModelItem(CommandProcessorContext cpc, EditingContext context, string columnName) { Debug.Assert(context != null, "The context argument cannot be null"); Debug.Assert(ScalarProperty == null, "Don't call this method if we already have a ModelItem"); Debug.Assert(_property != null, "The _property cannot be null."); Debug.Assert( MappingFunctionImport.FunctionImport != null && MappingFunctionImport.FunctionImportMapping != null, "The parent item isn't set up correctly"); Context = context; var fi = MappingFunctionImport.FunctionImport; var fim = MappingFunctionImport.FunctionImportMapping; if (_property != null && fi != null && fim != null) { // get the ReturnType of the FunctionImport EntityType entityType = null; ComplexType complexType = null; if (fi.IsReturnTypeEntityType) { entityType = fi.ReturnTypeAsEntityType.Target; } else if (fi.IsReturnTypeComplexType && fi.ReturnTypeAsComplexType.Target != null) { complexType = fi.ReturnTypeAsComplexType.Target; } // create a context if we weren't passed one if (cpc == null) { cpc = new CommandProcessorContext( Context, EfiTransactionOriginator.MappingDetailsOriginatorId, Resources.Tx_ChangeScalarProperty); } // first we need to create a FunctionImportTypeMapping element (either EntityTypeMapping or ComplexTypeMapping) var cmd = entityType != null ? new CreateFunctionImportTypeMappingCommand(MappingFunctionImport.FunctionImportMapping, entityType) : new CreateFunctionImportTypeMappingCommand(MappingFunctionImport.FunctionImportMapping, complexType); // create the ScalarProperty var cmd2 = new CreateFunctionImportScalarPropertyCommand(cmd, _property, columnName); // set up our post event to fix up the view model cmd2.PostInvokeEvent += (o, eventsArgs) => { var sp = cmd2.ScalarProperty; Debug.Assert(sp != null, "Didn't get good ScalarProperty out of the command"); // fix up our view model (we don't have to add this to the parent's children collection // because we created a placeholder row already for each property) ModelItem = sp; }; // now make the change var cp = new CommandProcessor(cpc, cmd, cmd2); cp.Invoke(); } }
protected override void InvokeInternal(CommandProcessorContext cpc) { // safety check, this should never be hit Debug.Assert( _conceptualEntityType != null && _function != null, "InvokeInternal is called when _conceptualEntityType or _function is null"); if (_conceptualEntityType == null || _function == null) { throw new InvalidOperationException("InvokeInternal is called when _conceptualEntityType or _function is null"); } // see if we have the ETM we need, if not create it var entityTypeMapping = ModelHelper.FindEntityTypeMapping( cpc, _conceptualEntityType, EntityTypeMappingKind.Function, true); Debug.Assert(entityTypeMapping != null, "Failed to create the EntityTypeMapping to house this item"); if (entityTypeMapping == null) { throw new ParentItemCreationFailureException(); } // if we created a new ETM, then we'll need to also create the ModificationFunctionMapping if (entityTypeMapping.ModificationFunctionMapping == null) { entityTypeMapping.ModificationFunctionMapping = new ModificationFunctionMapping(entityTypeMapping, null); XmlModelHelper.NormalizeAndResolve(entityTypeMapping.ModificationFunctionMapping); } Debug.Assert( entityTypeMapping.ModificationFunctionMapping != null, "Failed to create the ModificationFunctionMapping node to house this item"); if (entityTypeMapping.ModificationFunctionMapping == null) { throw new ParentItemCreationFailureException(); } // now go and actually create the item if (_type == ModificationFunctionType.Insert) { _modificationFunction = new InsertFunction(entityTypeMapping.ModificationFunctionMapping, null); entityTypeMapping.ModificationFunctionMapping.InsertFunction = _modificationFunction as InsertFunction; } else if (_type == ModificationFunctionType.Update) { _modificationFunction = new UpdateFunction(entityTypeMapping.ModificationFunctionMapping, null); entityTypeMapping.ModificationFunctionMapping.UpdateFunction = _modificationFunction as UpdateFunction; } else if (_type == ModificationFunctionType.Delete) { _modificationFunction = new DeleteFunction(entityTypeMapping.ModificationFunctionMapping, null); entityTypeMapping.ModificationFunctionMapping.DeleteFunction = _modificationFunction as DeleteFunction; } Debug.Assert(_modificationFunction != null, "Failed to create the new function mapping"); if (_modificationFunction == null) { throw new ItemCreationFailureException(); } // set the function into the function mapping _modificationFunction.FunctionName.SetRefName(_function); // set the RowsAffectedParameter var cmd = new SetRowsAffectedParameterCommand(_modificationFunction, _rowsAffectedParameter); CommandProcessor.InvokeSingleCommand(cpc, cmd); XmlModelHelper.NormalizeAndResolve(_modificationFunction); }
/// <summary> /// Invokes a single command against the CommandProcessor. /// </summary> internal static void InvokeSingleCommand(CommandProcessorContext cpc, Command cmd) { var cp = new CommandProcessor(cpc, cmd); cp.Invoke(); }
/// <summary> /// Creates a new MappingFragment in the existing EntityTypeMapping /// based on another MappingFragment (fragToClone) in a different artifact. /// All the other parameters are presumed to already exist in the same artifact /// as the EntityTypeMapping. /// </summary> internal static MappingFragment CloneMappingFragment( CommandProcessorContext cpc, MappingFragment fragToClone, EntityTypeMapping existingEntityTypeMapping, StorageEntitySet existingEntitySet) { var createFragmentCommand = new CreateMappingFragmentCommand(existingEntityTypeMapping, existingEntitySet); var cp = new CommandProcessor(cpc, createFragmentCommand); cp.Invoke(); var frag = createFragmentCommand.MappingFragment; Debug.Assert(frag != null, "Could not locate or create the required mapping fragment"); if (frag != null) { foreach (var sp in fragToClone.ScalarProperties()) { Property entityProperty = null; if (sp.Name != null && sp.Name.Target != null && sp.Name.Target.LocalName != null && sp.Name.Target.LocalName.Value != null) { entityProperty = ModelHelper.FindPropertyForEntityTypeMapping( existingEntityTypeMapping, sp.Name.Target.LocalName.Value); Debug.Assert( entityProperty != null, "Cannot find Property with name " + sp.Name.Target.LocalName.Value + " for EntityTypeMapping " + existingEntityTypeMapping.ToPrettyString()); } Property tableColumn = null; if (frag.StoreEntitySet != null && frag.StoreEntitySet.Target != null && frag.StoreEntitySet.Target.EntityType != null && frag.StoreEntitySet.Target.EntityType.Target != null && sp.ColumnName != null && sp.ColumnName.Target != null && sp.ColumnName.Target.LocalName != null && sp.ColumnName.Target.LocalName.Value != null) { tableColumn = ModelHelper.FindProperty( frag.StoreEntitySet.Target.EntityType.Target, sp.ColumnName.Target.LocalName.Value); Debug.Assert( tableColumn != null, "Cannot find Property with name " + sp.ColumnName.Target.LocalName.Value + " for EntityType " + frag.StoreEntitySet.Target.EntityType.Target.ToPrettyString()); } if (entityProperty != null && tableColumn != null) { var createScalarCommand = new CreateFragmentScalarPropertyCommand(frag, entityProperty, tableColumn); var cp2 = new CommandProcessor(cpc, createScalarCommand); cp2.Invoke(); } } } return(frag); }
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); }
/// <summary> /// Invokes a single command against the CommandProcessor. /// </summary> internal static void InvokeSingleCommand(CommandProcessorContext cpc, Command cmd) { var cp = new CommandProcessor(cpc, cmd); cp.Invoke(); }
protected override void InvokeInternal(CommandProcessorContext cpc) { // safety check, this should never be hit if ((_entityType == null && _complexType == null) || _functionImportMapping == null) { throw new InvalidOperationException( "InvokeInternal is called when _entityType or _complexType or _functionImportMapping is null."); } if (_functionImportMapping.ResultMapping == null) { _functionImportMapping.ResultMapping = new ResultMapping(_functionImportMapping, null); XmlModelHelper.NormalizeAndResolve(_functionImportMapping.ResultMapping); } // first check if we already have one (if found we'll simply return it) _createdTypeMapping = _entityType != null ? _functionImportMapping.ResultMapping.FindTypeMapping(_entityType) : _functionImportMapping.ResultMapping.FindTypeMapping(_complexType); if (_createdTypeMapping == null) { if (_entityType != null) { _createdTypeMapping = new FunctionImportEntityTypeMapping(_functionImportMapping.ResultMapping, null); _createdTypeMapping.TypeName.SetRefName(_entityType); } else { _createdTypeMapping = new FunctionImportComplexTypeMapping(_functionImportMapping.ResultMapping, null); _createdTypeMapping.TypeName.SetRefName(_complexType); } XmlModelHelper.NormalizeAndResolve(_createdTypeMapping); _functionImportMapping.ResultMapping.AddTypeMapping(_createdTypeMapping); } if (_createDefaultScalarProperties && _createdTypeMapping != null) { IEnumerable <Property> properties = null; if (_entityType != null) { properties = _entityType.Properties(); } else if (_complexType != null) { properties = _complexType.Properties(); } if (properties != null) { foreach (var prop in properties) { // Skip if the property is a Complex Property or if we already have the Scalar Property in the type mapping. if ((prop is ComplexConceptualProperty) == false && _createdTypeMapping.FindScalarProperty(prop) == null) { var columnName = (_mapPropertyNameToColumnName != null && _mapPropertyNameToColumnName.ContainsKey(prop.DisplayName) ? _mapPropertyNameToColumnName[prop.DisplayName] : prop.DisplayName); CommandProcessor.InvokeSingleCommand( cpc, new CreateFunctionImportScalarPropertyCommand(_createdTypeMapping, prop, columnName)); } } } } }
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) { var service = cpc.EditingContext.GetEFArtifactService(); var artifact = service.Artifact; // the model that we want to add the association to var model = artifact.StorageModel(); // check for uniqueness var assocName = Name; var assocSetName = assocName; if (UniquifyNames) { assocName = ModelHelper.GetUniqueName(typeof(Association), model, assocName); assocSetName = ModelHelper.GetUniqueName(typeof(AssociationSet), model.FirstEntityContainer, assocName); } else { // check for uniqueness of the association name string msg = null; if (ModelHelper.IsUniqueName(typeof(Association), model, assocName, false, out msg) == false) { throw new InvalidOperationException(msg); } // check for uniqueness of the association set name if (ModelHelper.IsUniqueName(typeof(AssociationSet), model.FirstEntityContainer, assocSetName, false, out msg) == false) { throw new InvalidOperationException(msg); } } // create the new item in our model var association = new Association(model, null); association.LocalName.Value = assocName; model.AddAssociation(association); XmlModelHelper.NormalizeAndResolve(association); // create the ends of the association var fkEnd = new AssociationEnd(association, null); fkEnd.Type.SetRefName(FkTable); fkEnd.Role.Value = FkRoleNameOverride ?? ModelHelper.CreateFKAssociationEndName(FkTable.LocalName.Value); if (FkMultiplicityOverride != null) { fkEnd.Multiplicity.Value = FkMultiplicityOverride; } else { fkEnd.Multiplicity.Value = DoesFkFormPk ? ModelConstants.Multiplicity_ZeroOrOne : ModelConstants.Multiplicity_Many; } association.AddAssociationEnd(fkEnd); XmlModelHelper.NormalizeAndResolve(fkEnd); var pkEnd = new AssociationEnd(association, null); pkEnd.Type.SetRefName(PkTable); pkEnd.Role.Value = PkRoleNameOverride ?? ModelHelper.CreatePKAssociationEndName(PkTable.LocalName.Value); if (PkMultiplicityOverride != null) { pkEnd.Multiplicity.Value = PkMultiplicityOverride; } else { pkEnd.Multiplicity.Value = IsNullableFk ? ModelConstants.Multiplicity_ZeroOrOne : ModelConstants.Multiplicity_One; } association.AddAssociationEnd(pkEnd); XmlModelHelper.NormalizeAndResolve(pkEnd); var cmd = new CreateAssociationSetCommand(assocSetName, association, ModelSpace.Storage); CommandProcessor.InvokeSingleCommand(cpc, cmd); var set = cmd.AssociationSet; Debug.Assert(set != null, "failed to create an AssociationSet"); Association = association; _createdAssociationFkEnd = fkEnd; _createdAssociationPkEnd = pkEnd; }
/// <summary> /// This will create a transaction if there isn't one already. If the CommandProcessorContext is already /// tracking a transaction, then a new one is NOT created. /// </summary> /// <param name="cpc"></param> /// <param name="element">The EFElement to delete</param> /// <param name="rebindAllBindings">Control whether all bindings in the artifact should be rebound</param> internal static void DeleteInTransaction(CommandProcessorContext cpc, DeleteEFElementCommand cmd, bool rebindAllBindings) { cmd.RebindAllBindings = rebindAllBindings; CommandProcessor.InvokeSingleCommand(cpc, cmd); }
// <summary> // The mapping view model contains a MappingEndScalarProperty for every key in each end. The user can clear out the // underlying scalar property, but that doesn't remove or add the MappingEndScalarProperty. We need the placeholder // in the view model to show the nodes in the Trid even if there isn't a mapping. Thus, we don't need to call // this.Parent.AddChild(this) since its already there. // </summary> internal override void CreateModelItem(CommandProcessorContext cpc, EditingContext context, EFElement underlyingModelItem) { Debug.Assert(underlyingModelItem != null, "The underlyingModelItem cannot be null"); var tableColumn = underlyingModelItem as Property; Debug.Assert(context != null, "The context argument cannot be null"); Debug.Assert(ScalarProperty == null, "Don't call this method if we already have a ModelItem"); Debug.Assert(tableColumn != null, "The tableColumn cannot be null."); if (tableColumn == null) { return; } Debug.Assert(tableColumn.EntityType.EntityModel.IsCSDL == false, "tableColumn must be a Store-side Property"); Context = context; // find the c-side property based on the passed in name var entityProperty = MappingAssociationSetEnd.ConceptualEntityType.GetFirstNamedChildByLocalName(Property) as Property; if (entityProperty == null) { // they might be trying to map a key from the base class EntityType topMostBaseType = MappingAssociationSetEnd.ConceptualEntityType.ResolvableTopMostBaseType; entityProperty = topMostBaseType.GetFirstNamedChildByLocalName(Property) as Property; } Debug.Assert(entityProperty != null, "Failed looking up entity property for ScalarProperty."); if (entityProperty == null) { return; } // create our context if we don't have one if (cpc == null) { cpc = new CommandProcessorContext( Context, EfiTransactionOriginator.MappingDetailsOriginatorId, Resources.Tx_CreateScalarProperty); } // create the right command CreateEndScalarPropertyCommand cmd = null; var end = MappingAssociationSetEnd.AssociationSetEnd.EndProperty; if (end == null) { // we don't have an end yet, this version will create an end as well as the scalar property cmd = new CreateEndScalarPropertyCommand( MappingAssociationSet.AssociationSet.AssociationSetMapping, MappingAssociationSetEnd.AssociationSetEnd, entityProperty, tableColumn); } else { cmd = new CreateEndScalarPropertyCommand(end, entityProperty, tableColumn); } // set up our post event to fix up the view model cmd.PostInvokeEvent += (o, eventArgs) => { var sp = cmd.ScalarProperty; Debug.Assert(sp != null, "cmd failed to generate ScalarProperty"); // fix up our view model (we don't have to add this to the parent's children collection // because we created a placeholder row already for every key in the entity) ModelItem = sp; }; try { // now make the change var cp = new CommandProcessor(cpc, cmd); cp.Invoke(); } catch { ModelItem = null; throw; } }
protected override void InvokeInternal(CommandProcessorContext cpc) { Debug.Assert(cpc != null, "InvokeInternal is called when ExitingFunctionScalarProperty is null."); // safety check, this should never be hit if (_existingFunctionScalarProperty == null) { throw new InvalidOperationException("InvokeInternal is called when ExitingFunctionScalarProperty is null."); } if (_propChain == null && _pointingNavProp == null && _param == null && _version != null) { // setting new version only if (string.Compare(_existingFunctionScalarProperty.Version.Value, _version, StringComparison.CurrentCulture) != 0) { var mfAncestor = _existingFunctionScalarProperty.GetParentOfType(typeof(ModificationFunction)) as ModificationFunction; Debug.Assert( mfAncestor != null, "Bad attempt to set version on FunctionScalarProperty which does not have a ModificationFunction ancestor"); if (mfAncestor != null) { Debug.Assert( mfAncestor.FunctionType == ModificationFunctionType.Update, "Bad attempt to set version on FunctionScalarProperty which has a ModificationFunction ancestor whose FunctionType is " + mfAncestor.FunctionType.ToString() + ". Should be " + ModificationFunctionType.Update.ToString()); if (mfAncestor.FunctionType == ModificationFunctionType.Update) { _existingFunctionScalarProperty.Version.Value = _version; } } } _updatedFunctionScalarProperty = _existingFunctionScalarProperty; return; } // if not just setting version then need to delete and re-create FunctionScalarProperty // to allow for changes in properties chain // where nulls have been passed in, use existing values (except for _pointingNavProp where null // indicates "use no NavProp for the new property") var mf = _existingFunctionScalarProperty.GetParentOfType(typeof(ModificationFunction)) as ModificationFunction; Debug.Assert(mf != null, "Bad attempt to change FunctionScalarProperty which does not have a ModificationFunction ancestor"); if (mf == null) { return; } var propChain = (_propChain != null ? _propChain : _existingFunctionScalarProperty.GetMappedPropertiesList()); var parameter = (_param != null ? _param : _existingFunctionScalarProperty.ParameterName.Target); var version = (_version != null ? _version : _existingFunctionScalarProperty.Version.Value); // now construct delete command for existing FunctionScalarProperty followed by create with new properties var cmd1 = _existingFunctionScalarProperty.GetDeleteCommand(); var cmd2 = new CreateFunctionScalarPropertyTreeCommand(mf, propChain, _pointingNavProp, parameter, version); cmd2.PostInvokeEvent += (o, eventsArgs) => { _updatedFunctionScalarProperty = cmd2.FunctionScalarProperty; Debug.Assert( _updatedFunctionScalarProperty != null, "CreateFunctionScalarPropertyTreeCommand should not result in null FunctionScalarProperty"); }; var cp = new CommandProcessor(cpc, cmd1, cmd2); try { cp.Invoke(); } finally { _updatedFunctionScalarProperty = null; } }
protected override void InvokeInternal(CommandProcessorContext cpc) { Debug.Assert(_entityType != null || _complexType != null, "Undefined parent type"); if (_entityType != null) { var propertyName = ModelHelper.GetUniqueConceptualPropertyName(_clipboardProperty.PropertyName, _entityType); if (_clipboardProperty.IsComplexProperty) { _createdProperty = CreateComplexPropertyCommand.CreateComplexProperty( cpc, propertyName, _entityType, _clipboardProperty.PropertyType, _clipboardProperty.ConcurrencyMode, _clipboardProperty.GetterAccessModifier, _clipboardProperty.SetterAccessModifier, _insertPosition); } else if (_clipboardProperty.IsConceptualProperty) { Debug.Assert(_entityType.EntityModel.IsCSDL, "This should be a c-side Entity"); if (_entityType.EntityModel.IsCSDL) { _createdProperty = CreatePropertyCommand.CreateConceptualProperty( cpc, propertyName, _entityType as ConceptualEntityType, _clipboardProperty.PropertyType, _clipboardProperty.IsNullable, _clipboardProperty.Default, _clipboardProperty.ConcurrencyMode, _clipboardProperty.GetterAccessModifier, _clipboardProperty.SetterAccessModifier, _clipboardProperty.MaxLength, _clipboardProperty.FixedLength, _clipboardProperty.Precision, _clipboardProperty.Scale, _clipboardProperty.Unicode, _clipboardProperty.Collation, _clipboardProperty.StoreGeneratedPattern, _insertPosition); } } else { Debug.Assert(_entityType.EntityModel.IsCSDL == false, "This should be a s-side Entity"); if (!_entityType.EntityModel.IsCSDL) { _createdProperty = CreatePropertyCommand.CreateStorageProperty( cpc, propertyName, _entityType as StorageEntityType, _clipboardProperty.PropertyType, _clipboardProperty.IsNullable, _clipboardProperty.Default, _clipboardProperty.MaxLength, DefaultableValueBoolOrNone.GetFromNullableBool(_clipboardProperty.FixedLength), _clipboardProperty.Precision, _clipboardProperty.Scale, DefaultableValueBoolOrNone.GetFromNullableBool(_clipboardProperty.Unicode), _clipboardProperty.Collation, _clipboardProperty.ConcurrencyMode); } } if (_clipboardProperty.IsKeyProperty) { var setKey = new SetKeyPropertyCommand(_createdProperty, true); CommandProcessor.InvokeSingleCommand(cpc, setKey); } AddAnnotations(_clipboardProperty, _createdProperty); } else { var cmd = new CopyComplexTypePropertyCommand(_clipboardProperty, _complexType); CommandProcessor.InvokeSingleCommand(cpc, cmd); _createdProperty = cmd.Property; } }
internal override void CreateModelItem(CommandProcessorContext cpc, EditingContext context, EFElement underlyingModelItem) { Debug.Assert(context != null, "The context argument cannot be null"); Debug.Assert(StorageEntityType == null, "Don't call this method if we already have a ModelItem"); Debug.Assert(MappingConceptualEntityType.ConceptualEntityType != null, "The parent item isn't set up correctly"); Debug.Assert(underlyingModelItem != null, "The underlyingModelItem cannot be null"); var storeEntityType = underlyingModelItem as EntityType; Debug.Assert( storeEntityType != null, "underlyingModelItem must be of type EntityType, actual type = " + underlyingModelItem.GetType().FullName); Debug.Assert(storeEntityType.EntityModel.IsCSDL == false, "The storageEntityType must not be a CSDL EntityType"); Context = context; ColumnMappings.Context = context; // create a context if we weren't passed one if (cpc == null) { cpc = new CommandProcessorContext( Context, EfiTransactionOriginator.MappingDetailsOriginatorId, Resources.Tx_CreateMappingFragment); } // create the MappingFragment - if we already have a default EntityTypeMapping then just add // the MappingFragment to that mapping, otherwise if we already have an IsTypeOf // EntityTypeMapping then add the MappingFragment to that, otherwise create an IsTypeOf // EntityTypeMapping and add the MappingFragment to that var cet = MappingConceptualEntityType.ConceptualEntityType; var defaultEtm = ModelHelper.FindEntityTypeMapping(cpc, cet, EntityTypeMappingKind.Default, false); var etmKind = (defaultEtm == null ? EntityTypeMappingKind.IsTypeOf : EntityTypeMappingKind.Default); var cmd = new CreateMappingFragmentCommand(cet, storeEntityType, etmKind); // add post-invoke event to fix up our view model cmd.PostInvokeEvent += (o, eventsArgs) => { // fix up our view model ModelItem = storeEntityType; Parent.AddChild(this); // assign the table to our container node as well ColumnMappings.ModelItem = storeEntityType; // now try and do some match ups between the entity and the table var mappingStrategy = ModelHelper.DetermineCurrentInheritanceStrategy(cet); var topMostBaseType = cet.ResolvableTopMostBaseType; foreach (var child in ColumnMappings.Children) { var msp = child as MappingScalarProperty; if (msp != null) { List<Property> properties; if (ModelHelper.FindScalarPropertyPathByLocalName(cet, msp.ColumnName, out properties)) { msp.CreateModelItem(cpc, _context, properties); } else if (InheritanceMappingStrategy.TablePerType == mappingStrategy && ModelHelper.FindScalarPropertyPathByLocalName(topMostBaseType, msp.ColumnName, out properties)) { msp.CreateModelItem(cpc, _context, properties); } } } }; try { // now update the model var cp = new CommandProcessor(cpc); cp.EnqueueCommand(cmd); cp.Invoke(); } catch { ModelItem = null; ColumnMappings.ModelItem = null; Parent.RemoveChild(this); throw; } }
/// <summary> /// Creates complex property with a default,unique name and passed complex type /// </summary> /// <param name="cpc"></param> /// <param name="parentComplexType">parent for new property</param> /// <param name="type">type for new property</param> /// <returns></returns> internal static Property CreateDefaultProperty(CommandProcessorContext cpc, ComplexType parentComplexType, ComplexType type) { var name = ModelHelper.GetUniqueName( typeof(ConceptualProperty), parentComplexType, ComplexConceptualProperty.DefaultComplexPropertyName); var cmd = new CreateComplexTypePropertyCommand(name, parentComplexType, type, false); var cp = new CommandProcessor(cpc, cmd); cp.Invoke(); return cmd.Property; }
// <summary> // The mapping view model contains a MappingScalarProperty for every column in the table. The user can clear out the // underlying scalar property, but that doesn't remove or add the MappingScalarProperty. We need the placeholder // in the view model to show the nodes in the Trid even if there isn't a mapping. Thus, we don't need to call // this.Parent.AddChild(this) since its already there. // </summary> internal void CreateModelItem(CommandProcessorContext cpc, EditingContext context, List<Property> propertiesChain) { Debug.Assert(propertiesChain != null, "The propertiesChain cannot be null"); Debug.Assert(context != null, "The context argument cannot be null"); Debug.Assert(ScalarProperty == null, "Don't call this method if we already have a ModelItem"); Debug.Assert(MappingStorageEntityType.StorageEntityType != null, "The parent item isn't set up correctly"); Debug.Assert(propertiesChain.Count > 0, "propertiesChain cannot be empty"); Context = context; // local shortcuts EntityType entityType = MappingConceptualEntityType.ConceptualEntityType; EntityType table = MappingStorageEntityType.StorageEntityType; // find the s-side property based on the value stored in this.ColumnName var tableColumn = table.GetFirstNamedChildByLocalName(ColumnName) as Property; Debug.Assert(tableColumn != null, "Failed looking up table column for ScalarProperty."); if (tableColumn == null) { return; } try { // now make the change if (cpc == null) { cpc = new CommandProcessorContext( Context, EfiTransactionOriginator.MappingDetailsOriginatorId, Resources.Tx_CreateScalarProperty); } var cmd = new CreateFragmentScalarPropertyTreeCommand(entityType, propertiesChain, tableColumn); cmd.PostInvokeEvent += (o, eventsArgs) => { var sp = cmd.ScalarProperty; Debug.Assert(sp != null, "CreateFragmentScalarPropertyTreeCommand failed to create ScalarProperty"); // fix up our view model (we don't have to add this to the parent's children collection // because we created a placeholder row already for every column in the table) ModelItem = sp; }; var cp = new CommandProcessor(cpc, cmd); cp.Invoke(); } catch { ModelItem = null; throw; } }
protected override void InvokeInternal(CommandProcessorContext cpc) { CreatedAssociation = ModelHelper.FindAssociation(cpc.Artifact.ConceptualModel(), Name); if (CreatedAssociation == null) { // This Association does not exist, create it base.InvokeInternal(cpc); } else { // The Association already exists, update it Debug.Assert( CreatedAssociation.AssociationEnds().Count == 2, "Association element is invalid, it should always have exactly 2 ends"); if (CreatedAssociation.AssociationEnds().Count == 2) { AssociationEnd principal; AssociationEnd dependent; ModelHelper.DeterminePrincipalDependentEndsForAnyAssociationType(CreatedAssociation, out principal, out dependent); if (principal.Type.Target == null || !string.Equals(principal.Type.Target.Name.Value, End1Entity.LocalName.Value, StringComparison.Ordinal)) { principal.Type.SetRefName(End1Entity); principal.Role.Value = End1Entity.LocalName.Value; } if (dependent.Type.Target == null || !string.Equals(dependent.Type.Target.Name.Value, End2Entity.LocalName.Value, StringComparison.Ordinal)) { dependent.Type.SetRefName(End2Entity); var endRoleValue = End2Entity.LocalName.Value; if (principal.Role.Value.Equals(endRoleValue)) { // avoid duplicate Role values between the two ends. This will occur in self-associations. // Appending "1" is consistent with how model-gen chooses a unique name. endRoleValue = endRoleValue + "1"; } dependent.Role.Value = endRoleValue; } if (!string.Equals(principal.Multiplicity.Value, End1Multiplicity, StringComparison.Ordinal)) { principal.Multiplicity.Value = End1Multiplicity; } if (!string.Equals(dependent.Multiplicity.Value, End2Multiplicity, StringComparison.Ordinal)) { dependent.Multiplicity.Value = End2Multiplicity; } // We have to resolve the association after both the principal and dependent have been updated here. The reason is because // if we resolve the principal and dependent separately we will end up with duplicate symbols in the symbol table because // the previous end didn't get removed. XmlModelHelper.NormalizeAndResolve(CreatedAssociation); // Also update the AssociationSet var associationSet = CreatedAssociation.AssociationSet; // It's possible for the association to exist but not the associationSet when a rename in the EntityDesigner is propagated // to the database and the resulting hydration events flow back up. if (associationSet == null) { var assocSetName = ModelHelper.GetUniqueName( typeof(AssociationSet), cpc.Artifact.ConceptualModel().FirstEntityContainer, Name); var cmd = new CreateAssociationSetCommand(assocSetName, CreatedAssociation); CommandProcessor.InvokeSingleCommand(cpc, cmd); associationSet = cmd.AssociationSet; } if (associationSet != null && principal.Type.Status == BindingStatus.Known && dependent.Type.Status == BindingStatus.Known && associationSet.PrincipalEnd != null && associationSet.DependentEnd != null) { associationSet.PrincipalEnd.Role.SetRefName(principal); associationSet.PrincipalEnd.EntitySet.SetRefName(principal.Type.Target.EntitySet); associationSet.DependentEnd.Role.SetRefName(dependent); associationSet.DependentEnd.EntitySet.SetRefName(dependent.Type.Target.EntitySet); XmlModelHelper.NormalizeAndResolve(associationSet); } var navProp1 = principal.GetAntiDependenciesOfType <NavigationProperty>() .FirstOrDefault(np => np.FromRole.Target == principal); if (navProp1 != null && ShouldCreateNavigationPropertyEnd1) { navProp1.Name.Value = NavigationPropertyInEnd1Entity; } var navProp2 = dependent.GetAntiDependenciesOfType <NavigationProperty>() .FirstOrDefault(np => np.FromRole.Target == dependent); if (navProp2 != null && ShouldCreateNavigationPropertyEnd2) { navProp2.Name.Value = NavigationPropertyInEnd2Entity; } } } }
// <summary> // The mapping view model contains a MappingFunctionScalarProperty for every parameter in the function. The user can clear out the // underlying scalar property, but that doesn't remove or add the MappingFunctionScalarProperty. We need the placeholder // in the view model to show the nodes in the Trid even if there isn't a mapping. Thus, we don't need to call // this.Parent.AddChild(this) since its already there. // </summary> internal void CreateModelItem(CommandProcessorContext cpc, EditingContext context, List<Property> propertiesChain) { Debug.Assert(propertiesChain != null, "The propertiesChain cannot be null"); Debug.Assert(context != null, "The context argument cannot be null"); Debug.Assert(ScalarProperty == null, "Don't call this method if we already have a ModelItem"); Debug.Assert(MappingModificationFunctionMapping.Function != null, "The parent item isn't set up correctly"); if (propertiesChain == null || context == null || ScalarProperty != null || MappingModificationFunctionMapping == null) { return; } Debug.Assert(propertiesChain.Count > 0, "propertiesChain cannot be empty"); if (propertiesChain.Count <= 0) { return; } Context = context; var mf = MappingModificationFunctionMapping.ModificationFunction; if (null == mf) { Debug.Fail("this.MappingModificationFunctionMapping.ModificationFunction is null"); return; } // use the stored Parameter var parameter = StoreParameter; if (parameter == null) { return; } // create a context if we weren't passed one if (cpc == null) { cpc = new CommandProcessorContext( Context, EfiTransactionOriginator.MappingDetailsOriginatorId, Resources.Tx_CreateScalarProperty); } // create the FunctionScalarProperty command (including any intermediate ComplexProperty's or AssociationEnd's) var version = (MappingModificationFunctionMapping.ModificationFunctionType == ModificationFunctionType.Update ? ModelConstants.FunctionScalarPropertyVersionCurrent : null); var cmd = new CreateFunctionScalarPropertyTreeCommand(mf, propertiesChain, _pointingNavProperty, parameter, version); // set up our post event to fix up the view model cmd.PostInvokeEvent += (o, eventsArgs) => { var fsp = cmd.FunctionScalarProperty; Debug.Assert(fsp != null, "CreateFunctionScalarPropertyTreeCommand did not create a FunctionScalarProperty"); // fix up our view model (we don't have to add this to the parent's children collection // because we created a placeholder row already for every parameter in the function) ModelItem = fsp; }; try { // now make the change var cp = new CommandProcessor(cpc, cmd); cp.Invoke(); } catch { ModelItem = null; throw; } }
internal void watermarkLabel_LinkClickedDeleteAssociation(object sender, LinkLabelLinkClickedEventArgs e) { var association = _toolWindow.GetAssociationFromLastPrimarySelection(); if (association == null) { Debug.Fail("association is null"); return; } var associationSetMappings = association.AssociationSet.GetAntiDependenciesOfType<AssociationSetMapping>(); Debug.Assert(_hostContext == _toolWindow.Context, "this.HostContext != to window.Context!"); if (HostContext == null) { Debug.Fail("Host context is null"); } else { var cpc = new CommandProcessorContext( _hostContext, EfiTransactionOriginator.MappingDetailsOriginatorId, Resources.Tx_DeleteAssociationSetMapping); var cp = new CommandProcessor(cpc); foreach (var associationSetMapping in associationSetMappings) { cp.EnqueueCommand(new DeleteEFElementCommand(associationSetMapping)); } if (cp.CommandCount > 0) { cp.Invoke(); } } // reset watermark text to account for the deleted ASM. if (_toolWindow.CanEditMappingsForAssociation(association, false)) { _toolWindow.SetUpAssociationDisplay(); } }
protected override void InvokeInternal(CommandProcessorContext cpc) { if (_diagram != null) { // Add diagram id information in the transaction context. // This is to ensure the diagram objects are created correctly. if (cpc.EfiTransaction.GetContextValue <DiagramContextItem>(EfiTransactionOriginator.TransactionOriginatorDiagramId) == null) { cpc.EfiTransaction.AddContextValue( EfiTransactionOriginator.TransactionOriginatorDiagramId, new DiagramContextItem(_diagram.Id.Value)); } } var service = cpc.EditingContext.GetEFArtifactService(); var artifact = service.Artifact; // the model that we want to add the entity to var model = ModelHelper.GetEntityModel(artifact, _modelSpace); var entitiesMap = new Dictionary <EntityTypeClipboardFormat, EntityType>(_clipboardEntities.ClipboardEntities.Count); // create copies of EntityTypes foreach (var clipboardEntity in _clipboardEntities.ClipboardEntities) { var cmd = new CopyEntityCommand(_diagram, clipboardEntity, _modelSpace); CommandProcessor.InvokeSingleCommand(cpc, cmd); entitiesMap.Add(clipboardEntity, cmd.EntityType); } // create copies of associations foreach (var clipboardAssociation in _clipboardEntities.ClipboardAssociations) { // Check if the association is in the Artifact/model. if (_diagram != null) { // Get the association by name. var association = artifact.ArtifactSet.LookupSymbol(clipboardAssociation.NormalizedName) as Association; if (association != null) { var entityTypesInAssociation = association.AssociationEnds().Select(ae => ae.Type.Target).ToList(); // Check whether the associated entity-types are created in the previous step. // When the user copy and paste an association and the associated entities in the same diagram, // we need to create a new copy of the association in the model. Without the check below, the code will determine that there is no need // to create the copy since the association exist in the model. if (entityTypesInAssociation.Except(entitiesMap.Values).Count() == 0) { // At this point we know that the association that is referred in clipboard exists in the current model. // Next we will check whether this association is represented in diagram or not. // if not, create a new association connector in the diagram. if (association.GetAntiDependenciesOfType <AssociationConnector>() .Count(ac => ac.Diagram.Id == _diagram.Id.Value) == 0) { // AssociationConnector is created by creating EntityTypeShapes that associationEnd refer to. foreach (var associationEnd in association.AssociationEnds()) { var entityType = associationEnd.Type.SafeTarget as ConceptualEntityType; Debug.Assert( entityType != null, "In: CopyEntitiesCommand's InvokeInternal, associationEnd's Type property should be typeof ConceptualEntityType"); if (entityType != null) { // CreateEntityTypeShapeAndConnectorsInDiagram method will check if the shape for the entity-type has been created; // and it will not create one if the shape already exists in the diagram. // Also, VerifyDiagramModelIntegrityVisitor will assert if there are duplicate diagram shapes (shapes that point to the same model element) // every-time a command transaction is committed. So adding another check to do the same thing here is redundant. CreateEntityTypeShapeCommand.CreateEntityTypeShapeAndConnectorsInDiagram( cpc, _diagram, entityType, false); } } } continue; } } } CopyAssociation(cpc, model, clipboardAssociation, entitiesMap); } // create copies of inheritances foreach (var inheritance in _clipboardEntities.ClipboardInheritances) { if (_diagram != null) { // Check if the underlying entity types are in the artifact/model to do that we need to: // - Get the Entity-Types by name. // - Check whether the entity-types match what were created in copy entities steps. var derivedEntity = artifact.ArtifactSet.LookupSymbol(inheritance.Key.NormalizedName) as EntityType; var baseEntity = artifact.ArtifactSet.LookupSymbol(inheritance.Value.NormalizedName) as EntityType; if (derivedEntity != null && baseEntity != null) { if (entitiesMap.Values.Contains(derivedEntity) && entitiesMap.Values.Contains(baseEntity)) { // check if the underlying entity-types are not in the diagram. // InheritanceConnector are created by ensuring both EntityTypeShapes are created. if (derivedEntity.GetAntiDependenciesOfType <EntityTypeShape>().Count(ets => ets.Diagram.Id == _diagram.Id.Value) == 0 && baseEntity.GetAntiDependenciesOfType <EntityTypeShape>() .Count(ets2 => ets2.Diagram.Id == _diagram.Id.Value) == 0) { // CreateEntityTypeShapeAndConnectorsInDiagram method will check if the shape for the entity-type has been created; // and it will not create one if the shape already exists in the diagram. // Also, VerifyDiagramModelIntegrityVisitor will assert if there are duplicate diagram shapes (shapes that point to the same model element) // every-time a command transaction is committed. So adding another check to do the same thing here is redundant. CreateEntityTypeShapeCommand.CreateEntityTypeShapeAndConnectorsInDiagram( cpc, _diagram, derivedEntity as ConceptualEntityType, false); CreateEntityTypeShapeCommand.CreateEntityTypeShapeAndConnectorsInDiagram( cpc, _diagram, baseEntity as ConceptualEntityType, false); } continue; } } } CopyInheritance(cpc, inheritance, entitiesMap); } }
protected override void InvokeInternal(CommandProcessorContext cpc) { var service = cpc.EditingContext.GetEFArtifactService(); var artifact = service.Artifact; // the model that we want to add the association to var model = artifact.ConceptualModel(); // check for uniqueness of the association and association set names // if uniquifyNames is true then make them unique, otherwise throw // an exception if they're not (always uniquify associationSetName // regardless as we get bugs if not) var assocName = Name; var assocSetName = assocName; if (UniquifyNames) { assocName = ModelHelper.GetUniqueName(typeof(Association), model, assocName); assocSetName = ModelHelper.GetUniqueName(typeof(AssociationSet), model.FirstEntityContainer, assocName); // ensure unique NavigationProperty names if (ShouldCreateNavigationPropertyEnd1 && !ModelHelper.IsUniquePropertyName(End1Entity, NavigationPropertyInEnd1Entity, true) || NavigationPropertyInEnd1Entity == End1Entity.LocalName.Value) { var namesToAvoid = new HashSet <string>(); namesToAvoid.Add(End1Entity.LocalName.Value); namesToAvoid.Add(NavigationPropertyInEnd2Entity); NavigationPropertyInEnd1Entity = ModelHelper.GetUniqueConceptualPropertyName( NavigationPropertyInEnd1Entity, End1Entity, namesToAvoid); } if (ShouldCreateNavigationPropertyEnd2 && !ModelHelper.IsUniquePropertyName(End2Entity, NavigationPropertyInEnd2Entity, true) || NavigationPropertyInEnd2Entity == End2Entity.LocalName.Value) { var namesToAvoid = new HashSet <string> { End2Entity.LocalName.Value, NavigationPropertyInEnd1Entity }; NavigationPropertyInEnd2Entity = ModelHelper.GetUniqueConceptualPropertyName( NavigationPropertyInEnd2Entity, End2Entity, namesToAvoid); } } else { assocSetName = ModelHelper.GetUniqueName(typeof(AssociationSet), model.FirstEntityContainer, assocName); string msg = null; if (!ModelHelper.IsUniqueName(typeof(Association), model, assocName, false, out msg)) { throw new InvalidOperationException(msg); } else if (!ModelHelper.IsUniqueName(typeof(AssociationSet), model.FirstEntityContainer, assocSetName, false, out msg)) { throw new InvalidOperationException(msg); } else if (ShouldCreateNavigationPropertyEnd1 && (!ModelHelper.IsUniquePropertyName(End1Entity, NavigationPropertyInEnd1Entity, true))) { msg = string.Format(CultureInfo.CurrentCulture, Resources.NAME_NOT_UNIQUE, NavigationPropertyInEnd1Entity); throw new InvalidOperationException(msg); } else if (ShouldCreateNavigationPropertyEnd2 && (!ModelHelper.IsUniquePropertyName(End2Entity, NavigationPropertyInEnd2Entity, true))) { msg = string.Format(CultureInfo.CurrentCulture, Resources.NAME_NOT_UNIQUE, NavigationPropertyInEnd2Entity); throw new InvalidOperationException(msg); } else if (NavigationPropertyInEnd1Entity == End1Entity.LocalName.Value) { msg = string.Format( CultureInfo.CurrentCulture, Resources.NavPropNameSameAsContainer, NavigationPropertyInEnd1Entity); throw new InvalidOperationException(msg); } else if (NavigationPropertyInEnd2Entity == End2Entity.LocalName.Value) { msg = string.Format( CultureInfo.CurrentCulture, Resources.NavPropNameSameAsContainer, NavigationPropertyInEnd2Entity); throw new InvalidOperationException(msg); } } // create the new item in our model var association = new Association(model, null); association.LocalName.Value = assocName; model.AddAssociation(association); XmlModelHelper.NormalizeAndResolve(association); // create the first end _end1 = new AssociationEnd(association, null); _end1.Type.SetRefName(End1Entity); _end1.Role.Value = End1Entity.LocalName.Value; _end1.Multiplicity.Value = End1Multiplicity; association.AddAssociationEnd(_end1); XmlModelHelper.NormalizeAndResolve(_end1); // create the second end _end2 = new AssociationEnd(association, null); _end2.Type.SetRefName(End2Entity); var endRoleValue = End2Entity.LocalName.Value; if (_end1.Role.Value.Equals(endRoleValue)) { // avoid duplicate Role values between the two ends. This will occur in self-associations. // Appending "1" is consistent with how model-gen chooses a unique name. endRoleValue = endRoleValue + "1"; } _end2.Role.Value = endRoleValue; _end2.Multiplicity.Value = End2Multiplicity; association.AddAssociationEnd(_end2); XmlModelHelper.NormalizeAndResolve(_end2); // create the association set for this association var cmd = new CreateAssociationSetCommand(assocSetName, association); CommandProcessor.InvokeSingleCommand(cpc, cmd); var set = cmd.AssociationSet; Debug.Assert(set != null, "unable to create association set"); CreateNavigationPropertyCommand navcmd; if (ShouldCreateNavigationPropertyEnd1) { navcmd = new CreateNavigationPropertyCommand(NavigationPropertyInEnd1Entity, End1Entity, association, _end1, _end2); CommandProcessor.InvokeSingleCommand(cpc, navcmd); } if (ShouldCreateNavigationPropertyEnd2) { navcmd = new CreateNavigationPropertyCommand(NavigationPropertyInEnd2Entity, End2Entity, association, _end2, _end1); CommandProcessor.InvokeSingleCommand(cpc, navcmd); } if (ShouldCreateForeignKeyProperties) { CreateForeignKeyProperties.AddRule(cpc, association); } CreatedAssociation = association; }
internal override void CreateModelItem(CommandProcessorContext cpc, EditingContext context, EFElement underlyingModelItem) { Debug.Assert(context != null, "context must not be null"); Debug.Assert(Condition == null, "Don't call this method if we already have a ModelItem"); Debug.Assert(MappingStorageEntityType.StorageEntityType != null, "The parent item isn't set up correctly"); Debug.Assert(underlyingModelItem != null, "underlyingModelItem must not be null"); var tableColumn = underlyingModelItem as Property; Debug.Assert( tableColumn != null, "underlyingModelItem must be of type Property, actual type = " + underlyingModelItem.GetType().FullName); // store this off in case we have recover the condition later (if it moves to another ETM on us) _modelItemColumnName = tableColumn.LocalName.Value; Context = context; // local shortcuts EntityType entityType = MappingConceptualEntityType.ConceptualEntityType; // create a context if we weren't passed one if (cpc == null) { cpc = new CommandProcessorContext( Context, EfiTransactionOriginator.MappingDetailsOriginatorId, Resources.Tx_CreateCondition); } // use empty string as a default condition value var cmd = new CreateFragmentConditionCommand(entityType, tableColumn, null, String.Empty); // set up our post event to fix up the view model cmd.PostInvokeEvent += (o, eventsArgs) => { var cond = cmd.CreatedCondition; Debug.Assert(cond != null, "cmd failed to create Condition"); // fix up our view model ModelItem = cond; Parent.AddChild(this); }; try { // now make the change var cp = new CommandProcessor(cpc, cmd); cp.Invoke(); } catch { ModelItem = null; Parent.RemoveChild(this); throw; } }
protected override void InvokeInternal(CommandProcessorContext cpc) { DesignerInfo designerInfo; Debug.Assert(cpc.Artifact != null, "Artifact was null"); if (Association != null && cpc.Artifact != null && cpc.Artifact.DesignerInfo() != null && cpc.Artifact.DesignerInfo().TryGetDesignerInfo(OptionsDesignerInfo.ElementName, out designerInfo)) { // APPDB_SCENARIO: We cannot use referential constraints for 0..1:0..1 or 1:1 associations, since these exist as configured // 0..1:* or 1:* associations and so introducing a referential constraint would cause validation errors. // Must use Referential Constraint for 1:0..1 relationship as using an AssociationSetMapping results in illegal reference to the same ID column twice (since the PK is also the FK) if (Association.IsOneToZeroOrOne || (UseReferentialConstraint && !(Association.IsZeroOrOneToZeroOrOne || Association.IsOneToOne))) { // We're including fk columns, so the update will consist of a ref constraint var createRefConCommand = new CreateOrUpdateReferentialConstraintCommand( (c, subCpc) => { var cmd = c as CreateOrUpdateReferentialConstraintCommand; cmd.PrincipalEnd = PrincipalEnd; cmd.DependentEnd = DependentEnd; cmd.PrincipalProperties = PrincipalProperties; cmd.DependentProperties = DependentProperties; return(cmd.PrincipalEnd != null && cmd.DependentEnd != null); }); CommandProcessor.InvokeSingleCommand(cpc, createRefConCommand); } else { // We're not including fk columns, so the update will consist of an association set mapping and a deletes of the fk columns (if they exist) // otherwise update AssociationSetMapping appropriately var createMapCommand = new CreateOrUpdateAssociationSetMappingCommand( (c, subCpc) => { var cmd = c as CreateOrUpdateAssociationSetMappingCommand; cmd.Association = Association; cmd.AssociationSet = AssociationSet; cmd.EntityContainerMapping = EntityContainerMapping; cmd.StorageEntitySet = StorageEntitySet; return(cmd.Association != null && cmd.AssociationSet != null && cmd.EntityContainerMapping != null && cmd.StorageEntitySet != null); }); CommandProcessor.InvokeSingleCommand(cpc, createMapCommand); // Delete the fk properties in the conceptual layer if they exist. Do not delete primary key properties though! if (!IncludeFkProperties) { var propertiesToDelete = DependentProperties.Where(p => p.EntityType != null && !p.EntityType.ResolvableKeys.Contains(p)).ToList(); foreach (var p in propertiesToDelete) { var deletePropertyCmd = new DeletePropertyCommand( (c, subCpc) => { var cmd = c as DeletePropertyCommand; cmd.EFElement = p; return(cmd.EFElement != null); }); CommandProcessor.InvokeSingleCommand(cpc, deletePropertyCmd); } } // Add or update the EndProperty elements for the AssociationSetMapping. Try to work out which end is the principal // end by looking at the multiplicity, since we don't have a referential constraint in this case. AssociationSetEnd principalSetEnd; AssociationSetEnd dependentSetEnd; Debug.Assert( AssociationSet.AssociationSetEnds().First().Role.Target != null, "Role Target for Association End was null, AssociationSetMapping update failed"); if (AssociationSet.AssociationSetEnds().First().Role.Target != null) { if (Association.End1.Multiplicity.Value == ModelConstants.Multiplicity_Many) { principalSetEnd = AssociationSet.AssociationSetEnds().Last(); dependentSetEnd = AssociationSet.AssociationSetEnds().First(); } else { principalSetEnd = AssociationSet.AssociationSetEnds().First(); dependentSetEnd = AssociationSet.AssociationSetEnds().Last(); } var dependentEndPropertyCmd = new CreateOrUpdateEndPropertyCommand( (c, subCpc) => { var cmd = c as CreateOrUpdateEndPropertyCommand; cmd.AssociationSetEnd = dependentSetEnd; cmd.AssociationSetMapping = createMapCommand.AssociationSetMapping; cmd.StorageKeyProperties = StorageDependentTypeKeyProperties; cmd.ConceptualKeyProperties = ConceptualDependentType.SafeInheritedAndDeclaredProperties.Where(p => p.IsKeyProperty); return(cmd.AssociationSetEnd != null && cmd.AssociationSetMapping != null); }); var principalEndPropertyCmd = new CreateOrUpdateEndPropertyCommand( (c, subCpc) => { var cmd = c as CreateOrUpdateEndPropertyCommand; cmd.AssociationSetEnd = principalSetEnd; cmd.AssociationSetMapping = createMapCommand.AssociationSetMapping; cmd.StorageKeyProperties = StorageDependentTypeForeignKeyProperties; cmd.ConceptualKeyProperties = ConceptualPrincipalType.SafeInheritedAndDeclaredProperties.Where(p => p.IsKeyProperty); return(cmd.AssociationSetEnd != null && cmd.AssociationSetMapping != null); }); CommandProcessor.InvokeSingleCommand(cpc, dependentEndPropertyCmd); CommandProcessor.InvokeSingleCommand(cpc, principalEndPropertyCmd); } } } }
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); } } } } }
/// <summary> /// This helper function creates a new entity in the conceptual model that is derived from the /// passed in entity. /// NOTE: If the cpc already has an active transaction, these changes will be in that transaction /// and the caller of this helper method must commit it to see these changes commited. /// </summary> /// <param name="cpc"></param> /// <param name="name">The name of the new, derived entity</param> /// <param name="baseType">The entity that this new type should derive from</param> /// <param name="uniquifyName">Flag whether the name should be checked for uniqueness and then changed as required</param> /// <returns>The new EntityType</returns> internal static ConceptualEntityType CreateDerivedEntityType( CommandProcessorContext cpc, string name, ConceptualEntityType baseType, bool uniquifyName) { var cet = new CreateEntityTypeCommand(name, uniquifyName); var inh = new CreateInheritanceCommand(cet, baseType); var cp = new CommandProcessor(cpc, cet, inh); cp.Invoke(); var derivedType = cet.EntityType as ConceptualEntityType; Debug.Assert(derivedType != null, "EntityType is not ConceptualEntityType"); return derivedType; }
protected override void InvokeInternal(CommandProcessorContext cpc) { Debug.Assert(Model != null, "Model was null, could not refresh PKs"); if (Model != null) { foreach (var entityType in Model.EntityTypes()) { var storageEntityType = entityType as StorageEntityType; var conceptualEntityType = entityType as ConceptualEntityType; SchemaQualifiedName entityNameToLookFor = null; if (storageEntityType != null) { var entitySet = storageEntityType.EntitySet as StorageEntitySet; entityNameToLookFor = new SchemaQualifiedName(entitySet.Schema.Value, entitySet.Table.Value); } else if (conceptualEntityType != null) { // If this EntityType has a base type, it should not have any keys. if (conceptualEntityType.BaseType.Target != null) { continue; } entityNameToLookFor = new SchemaQualifiedName(entityType.Name.Value); } Debug.Assert( entityNameToLookFor != null, "Should have created an entity name to look for based off of the current EntityType"); if (entityNameToLookFor != null) { var entityNameToRefresh = EntityTypePks.Keys.FirstOrDefault(name => name.Equals(entityNameToLookFor)); if (entityNameToRefresh != null) { // Update primary key properties that have changed foreach (var prop in entityType.Properties()) { SetKeyPropertyCommand cmd = null; if (prop.IsKeyProperty && EntityTypePks[entityNameToRefresh].All( c => string.Compare(c, prop.Name.Value, StringComparison.Ordinal) != 0)) { // This primary key was removed cmd = new SetKeyPropertyCommand(prop, false); } else if (prop.IsKeyProperty == false && EntityTypePks[entityNameToRefresh].Any( c => string.Compare(c, prop.Name.Value, StringComparison.Ordinal) == 0)) { // This primary key was added cmd = new SetKeyPropertyCommand(prop, true); } if (cmd != null) { CommandProcessor.InvokeSingleCommand(cpc, cmd); } } } else { // If we couldn't find the entity type in the dictionary, then it has no keys. Remove any existing ones. foreach (var keyProp in entityType.ResolvableKeys) { CommandProcessor.InvokeSingleCommand(cpc, new SetKeyPropertyCommand(keyProp, false)); } } } } } }
internal static void CreateEntityTypeShapeAndConnectorsInDiagram( CommandProcessorContext cpc, Diagram diagram, ConceptualEntityType entity, Color entityTypeShapeFillColor, bool createRelatedEntityTypeShapes) { // if the entity type shape has been created, return immediately. if (entity == null || entity.GetAntiDependenciesOfType <EntityTypeShape>().Count(ets => ets.Diagram.Id == diagram.Id.Value) > 0) { return; } var createEntityTypeShapecommand = new CreateEntityTypeShapeCommand(diagram, entity, entityTypeShapeFillColor); createEntityTypeShapecommand.PostInvokeEvent += (o, eventsArgs) => { if (createEntityTypeShapecommand.EntityTypeShape != null) { var relatedEntityTypesNotInDiagram = new List <EntityType>(); var entityTypesInDiagram = new HashSet <EntityType>(diagram.EntityTypeShapes.Select(ets => ets.EntityType.Target)); // add inheritance connector if the base type exists in the diagram. if (entity.SafeBaseType != null) { if (entityTypesInDiagram.Contains(entity.SafeBaseType)) { CommandProcessor.InvokeSingleCommand(cpc, new CreateInheritanceConnectorCommand(diagram, entity)); } else { relatedEntityTypesNotInDiagram.Add(entity.SafeBaseType); } } // add the inheritance connector if the derived type exist in the diagram. foreach (var derivedEntityType in entity.ResolvableDirectDerivedTypes) { if (entityTypesInDiagram.Contains(derivedEntityType)) { CommandProcessor.InvokeSingleCommand(cpc, new CreateInheritanceConnectorCommand(diagram, derivedEntityType)); } else { relatedEntityTypesNotInDiagram.Add(derivedEntityType); } } // Find all associations which the entity type participates. var participatingAssociations = Association.GetAssociationsForEntityType(entity); foreach (var association in participatingAssociations) { var entityTypesInAssociation = association.AssociationEnds().Select(ae => ae.Type.Target).ToList(); var entityTypesNotInDiagram = entityTypesInAssociation.Except(entityTypesInDiagram).ToList(); if (entityTypesNotInDiagram.Count == 0) { CommandProcessor.InvokeSingleCommand(cpc, new CreateAssociationConnectorCommand(diagram, association)); } relatedEntityTypesNotInDiagram.AddRange(entityTypesNotInDiagram); } if (createRelatedEntityTypeShapes) { foreach (var entityType in relatedEntityTypesNotInDiagram) { // we only want to bring entity-type directly related to the entity-type, so set createRelatedEntityTypeShapes flag to false. CreateEntityTypeShapeAndConnectorsInDiagram( cpc, diagram, entityType as ConceptualEntityType, entityTypeShapeFillColor, false); } } } }; CommandProcessor.InvokeSingleCommand(cpc, createEntityTypeShapecommand); }
protected override void InvokeInternal(CommandProcessorContext cpc) { Debug.Assert(cpc != null, "InvokeInternal is called when ExitingFunctionScalarProperty is null."); // safety check, this should never be hit if (_existingFunctionScalarProperty == null) { throw new InvalidOperationException("InvokeInternal is called when ExitingFunctionScalarProperty is null."); } if (_propChain == null && _pointingNavProp == null && _param == null && _version != null) { // setting new version only if (string.Compare(_existingFunctionScalarProperty.Version.Value, _version, StringComparison.CurrentCulture) != 0) { var mfAncestor = _existingFunctionScalarProperty.GetParentOfType(typeof(ModificationFunction)) as ModificationFunction; Debug.Assert( mfAncestor != null, "Bad attempt to set version on FunctionScalarProperty which does not have a ModificationFunction ancestor"); if (mfAncestor != null) { Debug.Assert( mfAncestor.FunctionType == ModificationFunctionType.Update, "Bad attempt to set version on FunctionScalarProperty which has a ModificationFunction ancestor whose FunctionType is " + mfAncestor.FunctionType.ToString() + ". Should be " + ModificationFunctionType.Update.ToString()); if (mfAncestor.FunctionType == ModificationFunctionType.Update) { _existingFunctionScalarProperty.Version.Value = _version; } } } _updatedFunctionScalarProperty = _existingFunctionScalarProperty; return; } // if not just setting version then need to delete and re-create FunctionScalarProperty // to allow for changes in properties chain // where nulls have been passed in, use existing values (except for _pointingNavProp where null // indicates "use no NavProp for the new property") var mf = _existingFunctionScalarProperty.GetParentOfType(typeof(ModificationFunction)) as ModificationFunction; Debug.Assert(mf != null, "Bad attempt to change FunctionScalarProperty which does not have a ModificationFunction ancestor"); if (mf == null) { return; } var propChain = (_propChain != null ? _propChain : _existingFunctionScalarProperty.GetMappedPropertiesList()); var parameter = (_param != null ? _param : _existingFunctionScalarProperty.ParameterName.Target); var version = (_version != null ? _version : _existingFunctionScalarProperty.Version.Value); // now construct delete command for existing FunctionScalarProperty followed by create with new properties var cmd1 = _existingFunctionScalarProperty.GetDeleteCommand(); var cmd2 = new CreateFunctionScalarPropertyTreeCommand(mf, propChain, _pointingNavProp, parameter, version); cmd2.PostInvokeEvent += (o, eventsArgs) => { _updatedFunctionScalarProperty = cmd2.FunctionScalarProperty; Debug.Assert( _updatedFunctionScalarProperty != null, "CreateFunctionScalarPropertyTreeCommand should not result in null FunctionScalarProperty"); }; var cp = new CommandProcessor(cpc, cmd1, cmd2); try { cp.Invoke(); } finally { _updatedFunctionScalarProperty = null; } }
/// <summary> /// This helper function will create a complex type using default name. /// NOTE: If the cpc already has an active transaction, these changes will be in that transaction /// and the caller of this helper method must commit it to see these changes commited. /// </summary> /// <param name="cpc"></param> /// <returns>The new ComplexType</returns> internal static ComplexType CreateComplexTypeWithDefaultName(CommandProcessorContext cpc) { var service = cpc.EditingContext.GetEFArtifactService(); var artifact = service.Artifact; // the model that we want to add the complex type to var model = artifact.ConceptualModel(); if (model == null) { throw new CannotLocateParentItemException(); } var complexTypeName = ModelHelper.GetUniqueNameWithNumber(typeof(ComplexType), model, Resources.Model_DefaultComplexTypeName); // go create it var cp = new CommandProcessor(cpc); var cmd = new CreateComplexTypeCommand(complexTypeName, false); cp.EnqueueCommand(cmd); cp.Invoke(); return cmd.ComplexType; }
private void ProcessMappingFragment(EntityInfo info, EntityType table, MappingFragment frag) { // move any scalar mappings to this fragment if they aren't there foreach (var sp in info.NonKeyScalars) { Debug.Assert(sp.ColumnName.Target != null, "Found a ScalarProperty with an unknown column binding"); if (sp.ColumnName.Target.Parent == table && sp.MappingFragment != frag) { // delete the old, create the new AddToDeleteList(sp); var cmd = new CreateFragmentScalarPropertyTreeCommand(frag, sp.GetMappedPropertiesList(), sp.ColumnName.Target); var cp = new CommandProcessor(_cpc, cmd); cp.Invoke(); } } // move any conditions to this fragment if they aren't there foreach (var cond in info.Conditions) { Debug.Assert(cond.ColumnName.Target != null, "Found a Condition with an unknown column binding"); if (cond.ColumnName.Target.Parent == table && cond.MappingFragment != frag) { // save off the condition information bool? isNull = null; if (cond.IsNull.Value == Condition.IsNullConstant) { isNull = true; } else if (cond.IsNull.Value == Condition.IsNotNullConstant) { isNull = false; } var conditionValue = cond.Value.Value; var column = cond.ColumnName.Target; // delete the old, create the new AddToDeleteList(cond); var cmd = new CreateFragmentConditionCommand(frag, column, isNull, conditionValue); var cp = new CommandProcessor(_cpc, cmd); cp.Invoke(); } } // build a list of all of the keys var keysToMap = new List<Property>(); keysToMap.AddRange(info.KeyProperties); // move any key scalar mappings to this fragment if they exist in a different one - provided they are for the same table foreach (var sp in info.KeyScalars) { Debug.Assert(sp.ColumnName.Target != null, "Found a ScalarProperty with an unknown column binding"); if (sp.ColumnName.Target.Parent == table && sp.MappingFragment != frag) { var property = sp.Name.Target; var column = sp.ColumnName.Target; // delete the old, create the new AddToDeleteList(sp); var cmd = new CreateFragmentScalarPropertyCommand(frag, property, column); var cp = new CommandProcessor(_cpc, cmd); cp.Invoke(); } // since we've mapped this one now, remove it from our list of things to do keysToMap.Remove(sp.Name.Target); } // if its TPH, all keys need to be here // (Note: if it's not TPH the user needs to specify any missing keys manually) if (info.InheritanceStrategy == InheritanceMappingStrategy.TablePerHierarchy) { // loop through the base most type's keys and add those that we haven't mapped foreach (var keyRemaining in keysToMap) { var sp = FindKeyMappingInAllParents(info, keyRemaining); if (sp != null && sp.ColumnName.Target != null && sp.ColumnName.Target.Parent == table) { var cmd = new CreateFragmentScalarPropertyCommand(frag, sp.Name.Target, sp.ColumnName.Target); var cp = new CommandProcessor(_cpc, cmd); cp.Invoke(); } } } // replicate all non-key base type scalars here if the parent uses a Default ETM // (since there is no parent IsTypeOf ETM from which to "inherit" them) if (info.Parent != null && info.Parent.UsesEntityTypeMappingKind(EntityTypeMappingKind.Default)) { // first gather the list of scalars from all parents var parentScalars = new List<ScalarProperty>(); GatherNonKeyScalarsFromAllParents(info.Parent, parentScalars); // then build a list of those scalars used in our fragment var existingMappedProperties = new HashSet<Property>(); foreach (var existingScalar in frag.ScalarProperties()) { existingMappedProperties.Add(existingScalar.Name.Target); } // finally, add those in that aren't already in the fragment foreach (var sp in parentScalars) { Debug.Assert(sp.ColumnName.Target != null, "Found a ScalarProperty with an unknown column binding"); // don't duplicate and only add those that use the same table as us if (existingMappedProperties.Contains(sp.Name.Target) == false && sp.ColumnName.Target.EntityType == table) { var cmd = new CreateFragmentScalarPropertyTreeCommand(frag, sp.GetMappedPropertiesList(), sp.ColumnName.Target); var cp = new CommandProcessor(_cpc, cmd); cp.Invoke(); existingMappedProperties.Add(sp.Name.Target); } } } // make sure that we don't have any extra scalars // so gather the list of all SPs we expect to be here var expectedMappedProperties = new List<Property>(); expectedMappedProperties.AddRange(info.KeyProperties); expectedMappedProperties.AddRange(info.NonKeyProperties); if (info.Parent != null && info.Parent.UsesEntityTypeMappingKind(EntityTypeMappingKind.Default)) { GatherNonKeyPropertiesFromAllParents(info.Parent, expectedMappedProperties); } // remove any that aren't in our expected list foreach (var sp in frag.ScalarProperties()) { if (expectedMappedProperties.Contains(sp.Name.Target) == false) { AddToDeleteList(sp); } } }
internal static bool UpdateEdmxAndEnvironment(ModelBuilderSettings settings) { var artifact = settings.Artifact as EntityDesignArtifact; if (artifact == null) { Debug.Fail("In trying to UpdateEdmxAndEnvironment(), No Artifact was found in the ModelBuilderSettings"); return false; } // Update the app. or web.config, register build providers etc ConfigFileHelper.UpdateConfig(settings); if (settings.SsdlStringReader != null && settings.MslStringReader != null) { // Create the XmlReaders for the ssdl and msl text var ssdlXmlReader = XmlReader.Create(settings.SsdlStringReader); var mslXmlReader = XmlReader.Create(settings.MslStringReader); // Set up our post event to clear out the error list var cmd = new ReplaceSsdlAndMslCommand(ssdlXmlReader, mslXmlReader); cmd.PostInvokeEvent += (o, e) => { var errorList = ErrorListHelper.GetSingleDocErrorList(e.CommandProcessorContext.Artifact.Uri); if (errorList != null) { errorList.Clear(); } }; // Update the model (all inside 1 transaction so we don't get multiple undo's/redo's) var editingContext = PackageManager.Package.DocumentFrameMgr.EditingContextManager.GetNewOrExistingContext(settings.Artifact.Uri); var cpc = new CommandProcessorContext( editingContext, EfiTransactionOriginator.GenerateDatabaseScriptFromModelId, Resources.Tx_GenerateDatabaseScriptFromModel); var cp = new CommandProcessor(cpc, cmd); var addUseLegacyProviderCommand = ModelHelper.CreateSetDesignerPropertyValueCommandFromArtifact( cpc.Artifact, OptionsDesignerInfo.ElementName, OptionsDesignerInfo.AttributeUseLegacyProvider, settings.UseLegacyProvider.ToString()); if (addUseLegacyProviderCommand != null) { cp.EnqueueCommand(addUseLegacyProviderCommand); } // When the user had a v2 edmx file (it can happen when creating a new empty model in a project targeting // .NET Framework 4 and the project does not have refereces to any of EF dlls) and selected EF6 in // the "create database from model" wizard we need to update the artifact to use v3 schemas otherwise // there will be a watermark saying that the edmx is not correct for the EF version and needs to be updated. // We only want to run this command if the version really changed to avoid the overhead. if (artifact.SchemaVersion != settings.TargetSchemaVersion) { cp.EnqueueCommand(new RetargetXmlNamespaceCommand(artifact, settings.TargetSchemaVersion)); } cp.Invoke(); } // First let's get the canonical file path since DTE needs this if (!string.IsNullOrEmpty(settings.DdlFileName) && settings.DdlStringReader != null) { var canonicalFilePath = string.Empty; try { var fi = new FileInfo(settings.DdlFileName); canonicalFilePath = fi.FullName; } catch (Exception e) { Debug.Fail( "We should have caught this exception '" + e.Message + "' immediately after the user clicked the 'Finish' button"); VsUtils.ShowErrorDialog( String.Format( CultureInfo.CurrentCulture, ModelWizard.Properties.Resources.ErrorCouldNotParseDdlFileName, settings.DdlFileName, e.Message)); return false; } // Output the DDL file, catch any Exceptions, display them, and revert // back to the last page of the wizard. try { OutputDdl(canonicalFilePath, settings.DdlStringReader); } catch (Exception e) { if (e.InnerException == null) { VsUtils.ShowErrorDialog( String.Format( CultureInfo.CurrentCulture, Resources.DatabaseCreation_ErrorWritingDdl, canonicalFilePath, e.Message)); } else { VsUtils.ShowErrorDialog( String.Format( CultureInfo.CurrentCulture, Resources.DatabaseCreation_ErrorWritingDdlWithInner, canonicalFilePath, e.Message, e.InnerException.Message)); } return false; } // Add DDL file to the project if it is inside the project string relativePath; if (VsUtils.TryGetRelativePathInProject(settings.Project, canonicalFilePath, out relativePath)) { AddDDLFileToProject(settings.Project, canonicalFilePath); } // Open the DDL file if it is not already open IVsUIHierarchy hier; uint itemId; IVsWindowFrame frame; if (VsShellUtilities.IsDocumentOpen( Services.ServiceProvider, canonicalFilePath, Guid.Empty, out hier, out itemId, out frame) == false) { VsShellUtilities.OpenDocument(Services.ServiceProvider, canonicalFilePath); } } return true; }
internal void ChangeScalarProperty(EditingContext context, List<Property> newPropertiesChain) { if (ModelItem != null) { var propertiesChain = ScalarProperty.GetMappedPropertiesList(); var changeNeeded = false; // is it different than what we have already? if (propertiesChain.Count != newPropertiesChain.Count) { changeNeeded = true; } else { for (var i = 0; i < propertiesChain.Count; i++) { if (propertiesChain[i] != newPropertiesChain[i]) { changeNeeded = true; break; } } } if (changeNeeded) { Debug.Assert(ScalarProperty.ColumnName.Status == BindingStatus.Known, "Table column not found"); if (ScalarProperty.ColumnName.Status == BindingStatus.Known) { // delete old and create new ScalarProperty in one transaction var cpc = new CommandProcessorContext( context, EfiTransactionOriginator.MappingDetailsOriginatorId, Resources.Tx_ChangeScalarProperty); var cmd1 = ScalarProperty.GetDeleteCommand(); var cmd2 = new CreateFragmentScalarPropertyTreeCommand( MappingConceptualEntityType.ConceptualEntityType, newPropertiesChain, ScalarProperty.ColumnName.Target); cmd2.PostInvokeEvent += (o, eventsArgs) => { var sp = cmd2.ScalarProperty; Debug.Assert(sp != null, "CreateFragmentScalarPropertyTreeCommand falied to create a ScalarProperty"); ModelItem = sp; }; var cp = new CommandProcessor(cpc, cmd1, cmd2); try { cp.Invoke(); } catch { ModelItem = null; throw; } } } } else { // if we don't have a scalar property, there is nothing to set this into; // create the scalar property first throw new InvalidOperationException(); } }
protected override void InvokeInternal(CommandProcessorContext cpc) { var service = cpc.EditingContext.GetEFArtifactService(); var artifact = service.Artifact; Debug.Assert(artifact != null, "Null Artifact"); if (null == artifact) { return; } // construct a mapping of the existing model's C-side objects // and their S-side identities before anything is updated var existingModel = new ExistingModelSummary(artifact); // replace the old SSDL with the new and fixup any references // in the MSL that broke because of the replacement of the SSDL // (i.e. the S-side Alias and S-side EntityContainer name) var replaceSsdlCommand = new ReplaceSsdlCommand(_newArtifactFromDB.StorageModel()); CommandProcessor.InvokeSingleCommand(cpc, replaceSsdlCommand); // remove any mappings with references which no longer work // with the new SSDL var deleteUnboundMappingsCommand = new DeleteUnboundMappingsCommand(); CommandProcessor.InvokeSingleCommand(cpc, deleteUnboundMappingsCommand); // remove any mappings which should no longer be mapped with the new SSDL // but actually are because a new S-side object with identical name // but different identity has been added var deleteChangedIdentityMappingsCommand = new DeleteChangedIdentityMappingsCommand(existingModel); CommandProcessor.InvokeSingleCommand(cpc, deleteChangedIdentityMappingsCommand); // from the temp model for the updated database determine which // C-side objects need to be added/updated and then update the // C- and M- side models appropriately var modelFromUpdatedDatabase = new UpdatedModelSummary(_newArtifactFromDB); var updateCsdlAndMslCommand = new UpdateConceptualAndMappingModelsCommand(existingModel, modelFromUpdatedDatabase); CommandProcessor.InvokeSingleCommand(cpc, updateCsdlAndMslCommand); // fix up Function Import parameters and add integrity checks if (artifact.MappingModel() != null && artifact.MappingModel().FirstEntityContainerMapping != null) { // Function Import parameters are now out-of-date compared to the updated Function ones. // We need to update them as otherwise there is no way to do so using Escher. foreach (var fim in artifact.MappingModel().FirstEntityContainerMapping.FunctionImportMappings()) { if (null != fim.FunctionImportName && null != fim.FunctionImportName.Target && null != fim.FunctionName && null != fim.FunctionName.Target) { CreateFunctionImportCommand.UpdateFunctionImportParameters( cpc, fim.FunctionImportName.Target, fim.FunctionName.Target); } } // Add integrity checks to enforce mapping rules foreach (var esm in artifact.MappingModel().FirstEntityContainerMapping.EntitySetMappings()) { EnforceEntitySetMappingRules.AddRule(cpc, esm); } // add the integrity check to propagate all appropriate StoreGeneratedPattern values to the S-side // Note: should not propagate "None"/defaulted values to prevent those C-side values overwriting // correctly updated S-side StoreGeneratedPattern values which were just received from the runtime PropagateStoreGeneratedPatternToStorageModel.AddRule(cpc, artifact, false); // Add integrity check to enforce synchronizing C-side Property facets to S-side values var shouldSynchronizePropertyFacets = ModelHelper.GetDesignerPropertyValueFromArtifactAsBool( OptionsDesignerInfo.ElementName, OptionsDesignerInfo.AttributeSynchronizePropertyFacets, OptionsDesignerInfo.SynchronizePropertyFacetsDefault(artifact), artifact); if (shouldSynchronizePropertyFacets) { PropagateStoragePropertyFacetsToConceptualModel.AddRule(cpc, artifact); } } }
protected override void InvokeInternal(CommandProcessorContext cpc) { var artifact = cpc.EditingContext.GetEFArtifactService().Artifact; if (null == artifact) { Debug.Fail("null artifact not allowed"); return; } // safety check, this should never be hit Debug.Assert(_schemaProcedure != null, "InvokeInternal is called when _schemaProcedure is null"); if (null == _schemaProcedure) { throw new InvalidOperationException("InvokeInternal is called when _schemaProcedure is null."); } var cModel = artifact.ConceptualModel(); if (null == cModel) { Debug.Fail("ConceptualEntityModel not allowed"); return; } var cContainer = cModel.FirstEntityContainer as ConceptualEntityContainer; if (null == cContainer) { Debug.Fail("ConceptualEntityContainer not allowed"); return; } var sModel = artifact.StorageModel(); if (null == sModel) { Debug.Fail("null StorageEntityModel not allowed"); return; } // determine matching Function var funcObj = DatabaseObject.CreateFromSchemaProcedure(_schemaProcedure); var function = ModelHelper.FindFunction(sModel, funcObj); if (null == function) { // in some error scenarios where the model has not been properly created we can be asked to create a FunctionImport for a Function which does not exist // if so just return without creating return; } // do not produce FunctionImports for composable Functions unless _shouldCreateComposableFunctionImport is true if (false == _shouldCreateComposableFunctionImport && function.IsComposable.Value) { return; } // determine FunctionImport name and make sure it is unique var functionImportName = OverrideNameValue; if (String.IsNullOrWhiteSpace(functionImportName)) { if (null == function.LocalName || string.IsNullOrEmpty(function.LocalName.Value)) { Debug.Fail("null or empty LocalName attribute for matching Function " + function); return; } functionImportName = ModelHelper.GetUniqueName(typeof(FunctionImport), cContainer, function.LocalName.Value); } else { #if DEBUG string errorMessage; var isUnique = ModelHelper.IsUniqueName(typeof(FunctionImport), cContainer, functionImportName, false, out errorMessage); Debug.Assert(isUnique, "If we gave CreateMatchingFunctionImportCommand a name, it should have been unique"); #endif } object returnType = null; ComplexType existingComplexTypeReturnType = null; if (OverrideReturnTypeValue == null) { // get return type of the Function returnType = ConstructReturnType(_schemaProcedure, cModel, sModel, functionImportName); if (null == returnType) { Debug.Fail("cannot determine return type for schemaProcedure " + _schemaProcedure); return; } } else { if (OverrideReturnTypeValue.Equals(ModelConstants.NoneValue, StringComparison.Ordinal)) { returnType = Resources.NoneDisplayValueUsedForUX; } else { var rawValue = ModelHelper.UnwrapCollectionAroundFunctionImportReturnType(OverrideReturnTypeValue); // Here we attempt to find the corresponding ReturnType for the given ReturnTypeOverride. // The ReturnTypeOverride will be specified as the actual XAttribute value of the return type if (OverrideEntitySetValue != null) { if (ModelHelper.FindEntitySet(cpc.Artifact.ConceptualModel(), OverrideEntitySetValue) != null) { // ReturnType is an EntityType returnType = ModelHelper.FindEntityTypeViaSymbol(cpc.Artifact.ConceptualModel(), rawValue); } } else if (!ModelHelper.AllPrimitiveTypes(artifact.SchemaVersion).Contains(rawValue)) { // ReturnType is a ComplexType existingComplexTypeReturnType = ModelHelper.FindComplexType(cpc.Artifact.ConceptualModel(), rawValue); returnType = existingComplexTypeReturnType; } else { returnType = rawValue; } } } // Composable functions that do not return collections (e.g. scalar valued functions) are not supported // and should not be imported to the conceptual model if (Resources.NoneDisplayValueUsedForUX.Equals(returnType) && function.IsComposable.Value) { return; } // list of commands to be executed IList <Command> commands = new List <Command>(); // if return type is the name of a ComplexType then create a new matching ComplexType CreateComplexTypeCommand createComplexTypeCommand = null; if (OverrideReturnTypeValue == null && returnType is string && false == Resources.NoneDisplayValueUsedForUX.Equals(returnType)) { createComplexTypeCommand = AddCreateComplexTypeCommands(sModel, returnType as string, _schemaProcedure.RawColumns, commands); } // if we created a ComplexType above then pass that as a pre-req to the CreateFunctionImport command, // otherwise just create the FunctionImport without the pre-req CreateFunctionImportCommand cmdFuncImp; if (createComplexTypeCommand == null) { if (returnType is EdmType) { // For the case where the FunctionImport should have a return type which is not a Complex Type but // simply a C-side primitive type we have to pass the _name_ of the C-side primitive type to // CreateFunctionImportCommand, rather than the type itself returnType = (returnType as EdmType).Name; } cmdFuncImp = new CreateFunctionImportCommand(cContainer, function, functionImportName, returnType); } else { cmdFuncImp = new CreateFunctionImportCommand(cContainer, function, functionImportName, createComplexTypeCommand); } commands.Add(cmdFuncImp); // now create the FunctionImportMapping to map the S-side Function to the C-side FunctionImport if (null != artifact.MappingModel() && null != artifact.MappingModel().FirstEntityContainerMapping) { var cmdFuncImpMapping = new CreateFunctionImportMappingCommand( artifact.MappingModel().FirstEntityContainerMapping, function, cmdFuncImp.Id); cmdFuncImpMapping.AddPreReqCommand(cmdFuncImp); commands.Add(cmdFuncImpMapping); IDictionary <string, string> mapPropertyNameToColumnName = null; if (_schemaProcedure != null) { mapPropertyNameToColumnName = ModelHelper.ConstructComplexTypePropertyNameToColumnNameMapping( _schemaProcedure.RawColumns.Select(c => c.Name).ToList()); } // Create explicit function-import result type mapping if the return type is a complex type. if (createComplexTypeCommand != null) { commands.Add( new CreateFunctionImportTypeMappingCommand(cmdFuncImpMapping, createComplexTypeCommand) { CreateDefaultScalarProperties = true, PropertyNameToColumnNameMap = mapPropertyNameToColumnName }); } else if (OverrideReturnTypeValue != null && existingComplexTypeReturnType != null) { commands.Add( new CreateFunctionImportTypeMappingCommand(cmdFuncImpMapping, existingComplexTypeReturnType) { CreateDefaultScalarProperties = true, PropertyNameToColumnNameMap = mapPropertyNameToColumnName }); } } // now invoke the list of commands if (null != commands) { var cp = new CommandProcessor(cpc, commands); cp.Invoke(); // assign the generated FunctionImport so this command can be used as input for others _generatedFunctionImport = cmdFuncImp.FunctionImport; } }
protected override void InvokeInternal(CommandProcessorContext cpc) { // get unique name for the property var propertyName = ModelHelper.GetUniqueName(typeof(ConceptualProperty), _parentComplexType, _clipboardProperty.PropertyName); if (!_clipboardProperty.IsComplexProperty) { // scalar property case var cmd = new CreateComplexTypePropertyCommand( propertyName, _parentComplexType, _clipboardProperty.PropertyType, _clipboardProperty.IsNullable); CommandProcessor.InvokeSingleCommand(cpc, cmd); _createdProperty = cmd.Property; } else { // complex property case // first try to find ComplexType by it's name var complexTypeNormalizedName = EFNormalizableItemDefaults.DefaultNameNormalizerForEDM( _parentComplexType, _clipboardProperty.PropertyType); var items = _parentComplexType.Artifact.ArtifactSet.GetSymbolList(complexTypeNormalizedName.Symbol); ComplexType complexType = null; foreach (var efElement in items) { // the GetSymbolList() method might return more than one element so choose the first ComplexType complexType = efElement as ComplexType; if (complexType != null) { break; } } if (complexType != null) { // if the ComplexType is found, simply use the create command var cmd = new CreateComplexTypePropertyCommand(propertyName, _parentComplexType, complexType, false); CommandProcessor.InvokeSingleCommand(cpc, cmd); _createdProperty = cmd.Property; } else { // in this case we're going to create ComplexProperty with unresolved type var complexProperty = new ComplexConceptualProperty(_parentComplexType, null); complexProperty.ComplexType.SetXAttributeValue(_clipboardProperty.PropertyType); // set the name and add to the parent entity complexProperty.LocalName.Value = propertyName; _parentComplexType.AddProperty(complexProperty); // set other attributes of the property complexProperty.Nullable.Value = BoolOrNone.FalseValue; XmlModelHelper.NormalizeAndResolve(complexProperty); Debug.Assert( complexProperty.ComplexType.Status != BindingStatus.Known, "Why didn't we find the ComplexType in the ArtifactSet previously?"); _createdProperty = complexProperty; } } // safety check Debug.Assert(_createdProperty != null, "We didn't get good Property out of the command"); if (_createdProperty != null) { // set Property attributes var cmd2 = new SetConceptualPropertyFacetsCommand( _createdProperty, _clipboardProperty.Default, _clipboardProperty.ConcurrencyMode, _clipboardProperty.GetterAccessModifier, _clipboardProperty.SetterAccessModifier, _clipboardProperty.MaxLength, DefaultableValueBoolOrNone.GetFromNullableBool(_clipboardProperty.FixedLength), _clipboardProperty.Precision, _clipboardProperty.Scale, DefaultableValueBoolOrNone.GetFromNullableBool(_clipboardProperty.Unicode), _clipboardProperty.Collation); CommandProcessor.InvokeSingleCommand(cpc, cmd2); } }
/// <summary> /// This helper function is an easy way to get a new entity type, entity set and key property in the /// new entity type created in the conceptual or storage model. /// NOTE: If the cpc already has an active transaction, these changes will be in that transaction /// and the caller of this helper method must commit it to see these changes commited. /// </summary> /// <param name="cpc"></param> /// <param name="name">The name of the new entity</param> /// <param name="setName">The name of the new set</param> /// <param name="createKeyProperty">A flag whether to create a new key property or not (sending false creates no new property)</param> /// <param name="propertyName">The name of the new property</param> /// <param name="propertyType">The type of the new property</param> /// <param name="modelSpace">Either Conceptual or Storage</param> /// <param name="uniquifyName">Flag whether the name should be checked for uniqueness and then changed as required</param> /// <param name="isDefaultName">Flag whether the name is the default for new entity types/sets</param> /// <returns>The new EntityType</returns> internal static EntityType CreateEntityTypeAndEntitySetAndProperty( CommandProcessorContext cpc, string name, string setName, bool createKeyProperty, string propertyName, string propertyType, string propertyStoreGeneratedPattern, ModelSpace modelSpace, bool uniquifyNames, bool isDefaultName = false) { var cp = new CommandProcessor(cpc); var cet = new CreateEntityTypeCommand(name, modelSpace, uniquifyNames); cet.CreateWithDefaultName = isDefaultName; cp.EnqueueCommand(cet); var ces = new CreateEntitySetCommand(setName, cet, modelSpace, uniquifyNames); cp.EnqueueCommand(ces); if (createKeyProperty) { var cpcd = new CreatePropertyCommand(propertyName, cet, propertyType, false); cpcd.IsIdProperty = true; cp.EnqueueCommand(cpcd); var skpc = new SetKeyPropertyCommand(cpcd, true); cp.EnqueueCommand(skpc); var ssgpc = new SetStoreGeneratedPatternCommand(cpcd, propertyStoreGeneratedPattern); cp.EnqueueCommand(ssgpc); } cp.Invoke(); return cet.EntityType; }
public void RunFinished() { if (_edmxItem == null) { if (_modelBuilderSettings.GenerationOption == ModelGenerationOption.EmptyModelCodeFirst || _modelBuilderSettings.GenerationOption == ModelGenerationOption.CodeFirstFromDatabase) { Debug.Assert( _modelBuilderSettings.ModelBuilderEngine == null ^ _modelBuilderSettings.GenerationOption == ModelGenerationOption.CodeFirstFromDatabase, "Model should be null for Empty Model and not null CodeFirst from database"); AddCodeFirstItems(); } return; } var fileExtension = Path.GetExtension(_edmxItem.FileNames[1]); Debug.Assert( _modelBuilderSettings.Project.Equals(_edmxItem.ContainingProject), "ActiveSolutionProject is not the EDMX file's containing project"); using (new VsUtils.HourglassHelper()) { var package = PackageManager.Package; Window window = null; try { ConfigFileHelper.UpdateConfig(_modelBuilderSettings); // save the model generated in the wizard UI. if (_modelBuilderSettings.GenerationOption == ModelGenerationOption.GenerateFromDatabase) { var writingModelWatch = new Stopwatch(); writingModelWatch.Start(); var modelEdmx = ((EdmxModelBuilderEngine)_modelBuilderSettings.ModelBuilderEngine).Edmx; if (!string.Equals(fileExtension, EntityDesignArtifact.ExtensionEdmx, StringComparison.OrdinalIgnoreCase)) { // convert the file if this isn't EDMX var edmxFileInfo = new FileInfo(_edmxItem.FileNames[1]); var conversionContext = new ModelConversionContextImpl( _edmxItem.ContainingProject, _edmxItem, edmxFileInfo, _modelBuilderSettings.TargetSchemaVersion, modelEdmx); VSArtifact.DispatchToConversionExtensions( EscherExtensionPointManager.LoadModelConversionExtensions(), fileExtension, conversionContext, loading: false); File.WriteAllText(edmxFileInfo.FullName, conversionContext.OriginalDocument); } else { // we need to use XmlWriter to output so that XmlDeclaration is preserved. using (var modelWriter = XmlWriter.Create( _edmxItem.FileNames[1], new XmlWriterSettings { Indent = true })) { modelEdmx.WriteTo(modelWriter); } } writingModelWatch.Stop(); VsUtils.LogOutputWindowPaneMessage( _edmxItem.ContainingProject, string.Format( CultureInfo.CurrentCulture, Properties.Resources.WritingModelTimeMsg, writingModelWatch.Elapsed)); } // set the ItemType for the generated .edmx file if (_modelBuilderSettings.VSApplicationType != VisualStudioProjectSystem.Website && string.Equals( fileExtension, EntityDesignArtifact.ExtensionEdmx, StringComparison.OrdinalIgnoreCase)) { _edmxItem.Properties.Item(ItemTypePropertyName).Value = EntityDeployBuildActionName; } // now open created file in VS using default viewer window = _edmxItem.Open(Constants.vsViewKindPrimary); Debug.Assert(window != null, "Unable to get window for created edmx file"); } finally { package.ModelGenErrorCache.RemoveErrors(_edmxItem.FileNames[1]); } // Construct an editing context and make all final edits that require the file is opened. var edmxFileUri = new Uri(_edmxItem.FileNames[1]); var designArtifact = package.ModelManager.GetNewOrExistingArtifact( edmxFileUri, new VSXmlModelProvider(package, package)) as EntityDesignArtifact; Debug.Assert( designArtifact != null, "artifact should be of type EntityDesignArtifact but received type " + designArtifact.GetType().FullName); Debug.Assert( designArtifact.StorageModel != null, "designArtifact StorageModel cannot be null for Uri " + edmxFileUri.AbsolutePath); Debug.Assert( designArtifact.ConceptualModel != null, "designArtifact ConceptualModel cannot be null for Uri " + edmxFileUri.AbsolutePath); if (designArtifact != null && designArtifact.StorageModel != null && designArtifact.ConceptualModel != null) { var designerSafeBeforeAddingTemplates = designArtifact.IsDesignerSafe; var editingContext = package.DocumentFrameMgr.EditingContextManager.GetNewOrExistingContext(designArtifact.Uri); Debug.Assert(editingContext != null, "Null EditingContext for artifact " + edmxFileUri.AbsolutePath); if (editingContext != null) { // Add DbContext templates when generation is GenerateFromDatabase. (connection is configured) if (_modelBuilderSettings.GenerationOption == ModelGenerationOption.GenerateFromDatabase) { new DbContextCodeGenerator().AddDbContextTemplates( _edmxItem, _modelBuilderSettings.UseLegacyProvider); } // Create FunctionImports for every new Function var cp = PrepareCommandsAndIntegrityChecks(_modelBuilderSettings, editingContext, designArtifact); if (DbContextCodeGenerator.TemplateSupported(_edmxItem.ContainingProject, package)) { // Add command setting CodeGenerationStrategy to "None" for EmptyModel. (connection is not yet configured) // NOTE: For EmptyModel, the templates will be added after the connection is configured. // (i.e. during "Generate Database from Model" or "Refresh from Database") if (_modelBuilderSettings.GenerationOption == ModelGenerationOption.EmptyModel) { var cmd = EdmUtils.SetCodeGenStrategyToNoneCommand(designArtifact); if (cmd != null) { if (cp == null) { var cpc = new CommandProcessorContext( editingContext, EfiTransactionOriginator.CreateNewModelId, Resources.Tx_SetCodeGenerationStrategy); cp = new CommandProcessor(cpc, cmd); } else { cp.EnqueueCommand(cmd); } } } } else { // Templates not supported, add reference to SDE. (.NET Framework 3.5) VsUtils.AddProjectReference(_edmxItem.ContainingProject, "System.Data.Entity"); } if (cp != null) { cp.Invoke(); } // save the artifact to make it look as though updates were part of creation _edmxItem.Save(); if (_modelBuilderSettings.GenerationOption == ModelGenerationOption.GenerateFromDatabase && !designerSafeBeforeAddingTemplates) { // If the artifact became safe after adding references we need to reload it (this can happen // on .NET Framework 4 where we would originally create a v3 edmx if the user selected EF6 - // the artifact will be flagged as invalid since there is no runtime which could handle v3 // but after we added references to EF6 the artifacts becomes valid and need to be reloaded). designArtifact.DetermineIfArtifactIsDesignerSafe(); if (designArtifact.IsDesignerSafe) { Debug.Assert(!designArtifact.IsDirty, "Reloading dirty artifact - changes will be lost."); // Since the artifact was originally not valid we did not create the diagram for it. // Using ReloadDocData will cause the diagram to be recreated. Note we don't need to // reload the artifact itself since it has not changed. ((DocData) VSHelpers.GetDocData(package, designArtifact.Uri.LocalPath)).ReloadDocData(0); } } } if (window != null) { window.Activate(); } } } }
public override void OnDoubleClick(DiagramPointEventArgs e) { var association = ModelElement; if (association != null) { var diagram = Diagram as EntityDesignerDiagram; if (diagram != null) { var ec = diagram.GetModel().EditingContext; var xref = ModelToDesignerModelXRef.GetModelToDesignerModelXRef(ec); var modelAssociation = xref.GetExisting(association) as Model.Entity.Association; Debug.Assert(modelAssociation != null, "couldn't find model association for connector"); if (modelAssociation != null) { var commands = ReferentialConstraintDialog.LaunchReferentialConstraintDialog(modelAssociation); var cpc = new CommandProcessorContext( ec, EfiTransactionOriginator.EntityDesignerOriginatorId, Resources.Tx_ReferentialContraint); var cp = new CommandProcessor(cpc); foreach (var c in commands) { cp.EnqueueCommand(c); } cp.Invoke(); } } } }
public void FunctionImportReturnComplexType() { UITestRunner.Execute(TestContext.TestName, () => { const string testName = "UndoRedo.FunctionImportReturnComplexType"; ExecuteUndoRedoTest( testName, "NorthwindModel.edmx", (commandProcessorContext, artifact) => { var dte = VsIdeTestHostContext.Dte; var commandProcessor = new CommandProcessor(commandProcessorContext); var createComplexTypeCmd = new CreateComplexTypeCommand("Sales_by_year_result", true); commandProcessor.EnqueueCommand(createComplexTypeCmd); commandProcessor.EnqueueCommand( new CreateComplexTypePropertyCommand("Column1", createComplexTypeCmd, "Int32", false)); commandProcessor.EnqueueCommand( new CreateFunctionImportCommand( artifact.GetFreshConceptualEntityContainer("NorthwindEntities"), artifact.GetFreshStorageFunction("Sales_by_Year"), "myfunctionimport", createComplexTypeCmd)); commandProcessor.Invoke(); Assert.IsNotNull(artifact.GetFreshComplexType("Sales_by_year_result")); Assert.IsNotNull(artifact.GetFreshComplexType("Sales_by_year_result")); Assert.IsNotNull(artifact.GetFreshFunctionImport("myfunctionimport")); Assert.AreEqual( "Collection(NorthwindModel.Sales_by_year_result)", ((SingleItemBinding<ComplexType>)artifact.GetFreshFunctionImport("myfunctionimport").ReturnType) .RefName); //Undo Redo Create FunctionImport dte.ExecuteCommandForOpenDocument(artifact.LocalPath(), UndoCommand); Assert.IsNull(artifact.GetFreshComplexType("Sales_by_year_result")); Assert.IsNull(artifact.GetFreshFunctionImport("myfunctionimport")); dte.ExecuteCommandForOpenDocument(artifact.LocalPath(), RedoCommand); Assert.IsNotNull(artifact.GetFreshComplexType("Sales_by_year_result")); Assert.IsNotNull(artifact.GetFreshFunctionImport("myfunctionimport")); Assert.AreEqual( "Collection(NorthwindModel.Sales_by_year_result)", ((SingleItemBinding<ComplexType>)artifact.GetFreshFunctionImport("myfunctionimport").ReturnType) .RefName); CommandProcessor.InvokeSingleCommand( commandProcessorContext, new CreateFunctionImportCommand( artifact.GetFreshConceptualEntityContainer("NorthwindEntities"), artifact.GetFreshStorageFunction("GetFreightCost"), "myfunctionimport2", "String")); Assert.IsNotNull(artifact.GetFreshFunctionImport("myfunctionimport2")); Assert.AreEqual( "Collection(String)", ((DefaultableValue<String>)artifact.GetFreshFunctionImport("myfunctionimport2").ReturnType).Value); createComplexTypeCmd = new CreateComplexTypeCommand("GetFreightCost_result", true); commandProcessor.EnqueueCommand(createComplexTypeCmd); commandProcessor.EnqueueCommand( new ChangeFunctionImportCommand( artifact.GetFreshConceptualEntityContainer("NorthwindEntities"), artifact.GetFreshFunctionImport("myfunctionimport2"), artifact.GetFreshStorageFunction("GetFreightCost"), "test123", /* isComposable */ BoolOrNone.FalseValue, createComplexTypeCmd)); commandProcessor.Invoke(); Assert.IsNull(artifact.GetFreshFunctionImport("myfunctionimport2")); Assert.IsNotNull(artifact.GetFreshFunctionImport("test123")); Assert.AreEqual( "Collection(NorthwindModel.GetFreightCost_result)", ((SingleItemBinding<ComplexType>)artifact.GetFreshFunctionImport("test123").ReturnType).RefName); Assert.IsNotNull(artifact.GetFreshComplexType("GetFreightCost_result")); // Undo redo "Change FunctionImport" dte.ExecuteCommandForOpenDocument(artifact.LocalPath(), UndoCommand); Assert.IsNull(artifact.GetFreshFunctionImport("test123")); Assert.IsNotNull(artifact.GetFreshFunctionImport("myfunctionimport2")); Assert.AreEqual( "Collection(String)", ((DefaultableValue<String>)artifact.GetFreshFunctionImport("myfunctionimport2").ReturnType).Value); dte.ExecuteCommandForOpenDocument(artifact.LocalPath(), RedoCommand); Assert.IsNull(artifact.GetFreshFunctionImport("myfunctionimport2")); Assert.IsNotNull(artifact.GetFreshFunctionImport("test123")); Assert.AreEqual( "Collection(NorthwindModel.GetFreightCost_result)", ((SingleItemBinding<ComplexType>)artifact.GetFreshFunctionImport("test123").ReturnType).RefName); Assert.IsNotNull(artifact.GetFreshComplexType("GetFreightCost_result")); }); }); }
public void Mapping_General_Blank() { UITestRunner.Execute(TestContext.TestName, () => { const string typePrefix = "Mapping_General_Blank"; const string testName = "UndoRedo." + typePrefix; ExecuteUndoRedoTest( testName, "BlankModel.edmx", (commandProcessorContext, artifact) => { const string entityType1Name = typePrefix + "_EntityType1"; const string entityType2Name = typePrefix + "_EntityType2"; const string entitySetName = typePrefix + "_EntitySet"; var dte = VsIdeTestHostContext.Dte; CreateDefaultEntityType(commandProcessorContext, entityType1Name, entitySetName); CreateEntityTypeCommand.CreateConceptualEntityTypeAndEntitySetAndProperty( commandProcessorContext, entityType2Name, entitySetName, /*createKeyProperty*/ false, null, null, null, /*uniquifyNames*/ true); new CommandProcessor( commandProcessorContext, new CreateInheritanceCommand( artifact.GetFreshConceptualEntity(entityType2Name), artifact.GetFreshConceptualEntity(entityType1Name))).Invoke(); // CREATE TWO ENTITY TYPE MAPPINGS WITHIN THE SAME ENTITY SET MAPPING var commandProcessor = new CommandProcessor(commandProcessorContext); commandProcessor.EnqueueCommand( new CreateEntityTypeMappingCommand(artifact.GetFreshConceptualEntity(entityType1Name))); commandProcessor.EnqueueCommand( new CreateEntityTypeMappingCommand(artifact.GetFreshConceptualEntity(entityType2Name))); commandProcessor.Invoke(); Assert.AreEqual(2, artifact.GetFreshEntitySetMapping(entitySetName).EntityTypeMappings().Count); // Undo redo "Create two EntityTypeMappings within same EntitySetMapping" dte.ExecuteCommandForOpenDocument(artifact.LocalPath(), UndoCommand); Assert.IsNull(artifact.GetFreshEntitySetMapping(entitySetName)); Assert.IsNotNull(artifact.GetFreshConceptualEntity(entityType1Name)); Assert.IsNotNull(artifact.GetFreshConceptualEntity(entityType2Name)); dte.ExecuteCommandForOpenDocument(artifact.LocalPath(), RedoCommand); Assert.AreEqual(2, artifact.GetFreshEntitySetMapping(entitySetName).EntityTypeMappings().Count); }); }); }
internal void ChangeFunctionScalarProperty(EditingContext context, List<Property> newPropertiesChain) { if (ScalarProperty == null) { // if we don't have a scalar property, there is nothing to set this into; // create the scalar property first throw new InvalidOperationException(); } else { // is the propertiesChain different from what we have already? var propertiesChain = ScalarProperty.GetMappedPropertiesList(); var changeNeeded = false; if (propertiesChain.Count != newPropertiesChain.Count) { changeNeeded = true; } else { for (var i = 0; i < propertiesChain.Count; i++) { if (propertiesChain[i] != newPropertiesChain[i]) { changeNeeded = true; break; } } // if no change needed yet, check NavProp as well if (changeNeeded == false) { // if this property is pointed to by a navigation property, then check if the // new navigation property is different from the old one if (ScalarProperty.AssociationEnd != null) { var currentNavProp = ModelHelper.FindNavigationPropertyForFunctionScalarProperty(ScalarProperty); // currentNavProp can be null if the NavProp has been deleted changeNeeded = (currentNavProp == null ? true : (currentNavProp != _pointingNavProperty)); } else { // the previous property was not pointed to by a navigation property but the new one is if (_pointingNavProperty != null) { changeNeeded = true; } } } } if (changeNeeded) { // delete old and create new FunctionScalarProperty in one transaction - this takes care of // removing any old ComplexProperty or AssociationEnd parent nodes as necessary var cpc = new CommandProcessorContext( context, EfiTransactionOriginator.MappingDetailsOriginatorId, Resources.Tx_ChangeScalarProperty); var version = (ScalarProperty.Version == null ? null : ScalarProperty.Version.Value); // Version is used only for Update ModificationFunctions var cmd = new ChangeFunctionScalarPropertyCommand( ScalarProperty, newPropertiesChain, _pointingNavProperty, StoreParameter, version); cmd.PostInvokeEvent += (o, eventsArgs) => { var fsp = cmd.FunctionScalarProperty; Debug.Assert(fsp != null, "ChangeFunctionScalarPropertyCommand failed to create a FunctionScalarProperty"); ModelItem = fsp; }; var cp = new CommandProcessor(cpc, cmd); try { cp.Invoke(); } catch { ModelItem = null; throw; } } } }
// <summary> // This lets you switch the underlyingModelItem. // </summary> // <param name="cpc">The transaction to use for this entire process, cannot be null</param> // <param name="context">The current EditingContext</param> // <param name="newUnderlyingModelItem">The new model item to switch to</param> // <param name="deleteModelItemOnly">If 'true' then the MappingEFElement will just have its model item switched, if 'false' then a new MappingEFElement will be create and this one will be deleted</param> internal void SwitchModelItem( CommandProcessorContext cpc, EditingContext context, EFElement newUnderlyingModelItem, bool deleteModelItemOnly) { Debug.Assert(cpc != null, "You should send a cpc to this function so that the entire switch is in a single transaction"); var cmd = new DelegateCommand( () => { if (deleteModelItemOnly) { DeleteModelItemsRecursive(this, cpc); CreateModelItem(cpc, context, newUnderlyingModelItem); } else { Delete(cpc); var newElement = CreateCreatorNodeCopy(); newElement.CreateModelItem(cpc, context, newUnderlyingModelItem); } }); var cp = new CommandProcessor(cpc, cmd); cp.Invoke(); }
protected override void InvokeInternal(CommandProcessorContext cpc) { Debug.Assert( _mode == Mode.EntityType || _mode == Mode.MappingFragment, "Unknown mode set in CreateFragmentScalarPropertyTreeCommand"); var cp = new CommandProcessor(cpc); CreateFragmentComplexPropertyCommand prereqCmd = null; for (var i = 0; i < _properties.Count; i++) { var property = _properties[i]; var complexConceptualProperty = property as ComplexConceptualProperty; if (complexConceptualProperty != null) { Debug.Assert(i < _properties.Count - 1, "Last property shouldn't be ComplexConceptualProperty"); CreateFragmentComplexPropertyCommand cmd = null; if (prereqCmd == null) { if (_mode == Mode.EntityType) { cmd = new CreateFragmentComplexPropertyCommand(_conceptualEntityType, complexConceptualProperty, _tableColumn); } else { cmd = new CreateFragmentComplexPropertyCommand(_mappingFragment, complexConceptualProperty); } } else { cmd = new CreateFragmentComplexPropertyCommand(prereqCmd, complexConceptualProperty); } prereqCmd = cmd; cp.EnqueueCommand(cmd); } else { Debug.Assert(i == _properties.Count - 1, "This should be the last property"); CreateFragmentScalarPropertyCommand cmd = null; if (prereqCmd == null) { if (_mode == Mode.EntityType) { cmd = new CreateFragmentScalarPropertyCommand(_conceptualEntityType, property, _tableColumn); } else { cmd = new CreateFragmentScalarPropertyCommand(_mappingFragment, property, _tableColumn); } } else { cmd = new CreateFragmentScalarPropertyCommand(prereqCmd, property, _tableColumn); } cp.EnqueueCommand(cmd); cp.Invoke(); _createdProperty = cmd.ScalarProperty; return; } } }