/// <summary> /// Creates a copy of Property from a Clipboard format in the specified EntityType and Position. /// </summary> /// <param name="entityType">The entity to create the property in</param> /// <param name="clipboardProperty"></param> /// <param name="insertPosition">Information where the property should be inserted to. If the parameter is null, the property will be placed as the last property of the entity.</param> /// <returns></returns> internal CopyPropertyCommand(PropertyClipboardFormat clipboardProperty, EntityType entity, InsertPropertyPosition insertPosition) { if (_insertPosition != null) { Debug.Assert( entity.EntityModel.IsCSDL, "You can only set insertPosition parameter if the EntityType is a ConceptualEntityType."); Debug.Assert( insertPosition.InsertAtProperty != null && insertPosition.InsertAtProperty.EntityType == entity, "Could not create complex property in the given insertPosition because insertPosition's Entity-Type is not the same as the entity-type which the property will be created in."); } CommandValidation.ValidateEntityType(entity); _clipboardProperty = clipboardProperty; _entityType = entity; _insertPosition = insertPosition; }
public void Invoke() { Debug.Assert(_association != null, "The Association reference is null"); // if the association was deleted in this transaction, just return since we won't need to process it if (_association == null || _association.XObject == null) { return; } // if foreign keys aren't supported in this EF version, then we skip all processing here. if (!EdmFeatureManager.GetForeignKeysInModelFeatureState(_association.Artifact.SchemaVersion).IsEnabled()) { return; } Debug.Assert(_association.EntityModel.IsCSDL, "Creating foreign key properties isn't valid for SSDL associations"); Debug.Assert( _association.AssociationEnds().Count == 2, "The association to be processed does not have 2 ends while trying to create foreign key properties"); Debug.Assert( _association.AssociationSet != null, "The association being processed does not have a valid AssociationSet while trying to create foreign key properties"); // remove any existing RC if (_association.ReferentialConstraint != null) { DeleteEFElementCommand.DeleteInTransaction(_context, _association.ReferentialConstraint); } // figure out the principal and dependent ends AssociationEnd principal = null; AssociationEnd dependent = null; ModelHelper.DeterminePrincipalDependentAssociationEnds( _association, out principal, out dependent, ModelHelper.DeterminePrincipalDependentAssociationEndsScenario.CreateForeignKeyProperties); if (principal != null && principal.Type.Target != null && dependent != null && dependent.Type.Target != null) { // many-to-many associations don't need foreign key properties if (principal.Multiplicity.Value == ModelConstants.Multiplicity_Many && dependent.Multiplicity.Value == ModelConstants.Multiplicity_Many) { return; } var principalPropertyRefs = new HashSet<Property>(); var dependentPropertyRefs = new HashSet<Property>(); // add properties to the dependent side IEnumerable<Property> pkeys; var cet = principal.Type.Target as ConceptualEntityType; if (cet != null) { // the principal is a c-side entity pkeys = cet.ResolvableTopMostBaseType.ResolvableKeys; } else { // the principal is an s-side entity pkeys = principal.Type.Target.ResolvableKeys; } foreach (var pkey in pkeys) { // build up the foreign key name, add an '_' if the resulting name wouldn't be camel-case // e.g. // Order and Id become "OrderId" // order and id become "order_id" // // get a unique name for this new property var fkeyName = string.Format( CultureInfo.CurrentCulture, "{0}{1}{2}", principal.Type.Target.LocalName.Value, (char.IsUpper(pkey.LocalName.Value, 0) ? "" : "_"), pkey.LocalName.Value); fkeyName = ModelHelper.GetUniqueName(typeof(Property), dependent.Type.Target, fkeyName); // tweak the properties; we are using the copy/paste process since we have to // copy all facets of the pk and that code does this already var pcf = new PropertyClipboardFormat(pkey); pcf.PropertyName = fkeyName; pcf.IsKeyProperty = false; pcf.IsNullable = (principal.Multiplicity.Value == ModelConstants.Multiplicity_ZeroOrOne ? true : false); pcf.StoreGeneratedPattern = string.Empty; pcf.GetterAccessModifier = string.Empty; pcf.SetterAccessModifier = string.Empty; // create the new property var cmd = new CopyPropertyCommand(pcf, dependent.Type.Target); CommandProcessor.InvokeSingleCommand(_context, cmd); var fkey = cmd.Property; // build up our list of keys Debug.Assert(fkey != null, "CreateForeignKeyProperties was not able to create a foreign key"); if (fkey != null) { principalPropertyRefs.Add(pkey); dependentPropertyRefs.Add(fkey); } } // create the new RC Debug.Assert( principalPropertyRefs.Count == dependentPropertyRefs.Count, "List of keys are mismatched while trying to create a Ref Constraint"); if (principalPropertyRefs.Count > 0 && dependentPropertyRefs.Count > 0 && principalPropertyRefs.Count == dependentPropertyRefs.Count) { var cmd = new CreateReferentialConstraintCommand(principal, dependent, principalPropertyRefs, dependentPropertyRefs); CommandProcessor.InvokeSingleCommand(_context, cmd); } } }
/// <summary> /// Creates a copy of Property from a Clipboard format in the specified ComplexType /// </summary> /// <param name="parentComplexType"></param> /// <param name="clipboardProperty"></param> /// <returns></returns> internal CopyComplexTypePropertyCommand(PropertyClipboardFormat clipboardProperty, ComplexType parentComplexType) { CommandValidation.ValidateComplexType(parentComplexType); _clipboardProperty = clipboardProperty; _parentComplexType = parentComplexType; }
/// <summary> /// Creates a copy of Property from a Clipboard format in the specified ComplexType /// </summary> /// <param name="complexType"></param> /// <param name="clipboardProperty"></param> /// <returns></returns> internal CopyPropertyCommand(PropertyClipboardFormat clipboardProperty, ComplexType complexType) { CommandValidation.ValidateComplexType(complexType); _clipboardProperty = clipboardProperty; _complexType = complexType; }
/// <summary> /// Creates a copy of Property from a Clipboard format in the specified EntityType /// </summary> /// <param name="entityType"></param> /// <param name="clipboardProperty"></param> /// <returns></returns> internal CopyPropertyCommand(PropertyClipboardFormat clipboardProperty, EntityType entity) : this(clipboardProperty, entity, null) { }
/// <summary> /// In the existing artifact create a new C-side Property /// in the existing EntityType plus a mapping based on the /// C-side and S-side Properties in the temp artifact /// </summary> private Property CreateNewConceptualPropertyAndMapping( CommandProcessorContext cpc, Property cSidePropInTempArtifact, Property sSidePropInTempArtifact, EntityType existingEntityType) { Debug.Assert(cSidePropInTempArtifact != null, "Null C-side Property"); Debug.Assert(cSidePropInTempArtifact.EntityType.EntityModel.IsCSDL, "cSidePropInTempArtifact must be C-side"); Debug.Assert(sSidePropInTempArtifact != null, "Null S-side Property"); Debug.Assert(!sSidePropInTempArtifact.EntityType.EntityModel.IsCSDL, "sSidePropInTempArtifact must be S-side"); Debug.Assert(existingEntityType != null, "Null existing EntityType"); Debug.Assert(existingEntityType.EntityModel.IsCSDL, "Existing EntityType must be C-side"); var pcf = new PropertyClipboardFormat(cSidePropInTempArtifact); Debug.Assert( pcf != null, "Could not construct PropertyClipboardFormat for C-side Property " + cSidePropInTempArtifact.ToPrettyString()); if (null == pcf) { return null; } else { // store off matching S-side property in the existing // artifact for mapping below var sSidePropInExistingArtifact = FindSSidePropInExistingArtifact(sSidePropInTempArtifact); Debug.Assert( null != sSidePropInExistingArtifact, "Cannot find S-side Property matching the one in the temp artifact " + sSidePropInTempArtifact.ToPrettyString()); // create the C-side Property in the existing artifact var cmd = new CopyPropertyCommand(pcf, existingEntityType); CommandProcessor.InvokeSingleCommand(cpc, cmd); var cSidePropInExistingArtifact = cmd.Property; // now create the mapping for the C-side Property just created if (null != cSidePropInExistingArtifact && null != sSidePropInExistingArtifact) { var cmd2 = new CreateFragmentScalarPropertyCommand( existingEntityType, cSidePropInExistingArtifact, sSidePropInExistingArtifact); CommandProcessor.InvokeSingleCommand(cpc, cmd2); } return cSidePropInExistingArtifact; } }