/// <summary> /// Creates a command of that can swap a Navigation Property association ends. /// </summary> /// <param name="property">The navigation property to change</param> /// <param name="association">The association to use.</param> /// <param name="end1">The first point to swap</param> /// <param name="end2">The second point to swap</param> internal ChangeNavigationPropertyCommand( NavigationProperty property, Association association, AssociationEnd end1, AssociationEnd end2) { if (property == null) { throw new ArgumentNullException("property"); } if (association == null) { throw new ArgumentNullException("association"); } if (end1 == null) { throw new ArgumentNullException("end1"); } if (end2 == null) { throw new ArgumentNullException("end2"); } _property = property; _association = association; _end1 = end1; _end2 = end2; }
public AssociationEndEditor(AssociationEnd associationEnd) : this() { AssociationEnd = associationEnd; this.tbRole.Text = associationEnd.Name; this.lClass.Content = associationEnd.Class.Name; this.tbLower.Text = associationEnd.Lower.ToString(); this.tbUpper.Text = associationEnd.Upper.ToString(); switch (associationEnd.Aggregation) { case AggregationKind.none: cbType.SelectedIndex = 0; break; case AggregationKind.shared: cbType.SelectedIndex = 1; break; case AggregationKind.composite: cbType.SelectedIndex = 2; break; } oldKindIndex = cbType.SelectedIndex; }
private void CompareAssociationEnd(AssociationEnd expectedEnd, AssociationEnd actualEnd) { this.SatisfiesEquals(expectedEnd.RoleName, actualEnd.RoleName, "RoleName not as expeted."); this.SatisfiesEquals(expectedEnd.Multiplicity, actualEnd.Multiplicity, "Multiplicity does not match on AssociationEnd '{0}'.", expectedEnd.RoleName); this.SatisfiesEquals(expectedEnd.EntityType.FullName, actualEnd.EntityType.FullName, "EntityType name does not match on AssociationEnd '{0}'.", expectedEnd.RoleName); this.SatisfiesEquals(expectedEnd.DeleteBehavior, actualEnd.DeleteBehavior, "DeleteBehavior does not match on AssociationEnd '{0}'.", expectedEnd.RoleName); }
private static bool DoesEndNeedCondition(AssociationEnd end, AssociationEnd otherEnd, EntityType associationSetMappingTable) { if (end.Multiplicity.Value == ModelConstants.Multiplicity_ZeroOrOne) { return(true); } var cet = end.Type.Target as ConceptualEntityType; Debug.Assert(end.Type.Target != null ? cet != null : true, "EntityType is not a ConceptualEntityType"); if (cet != null && cet.HasResolvableBaseType) { // the subtype is mapped using TPH EntityType tphTable = null; if (IsMappedUsingTph(cet, out tphTable)) { // the association is not *:* if (!(end.Multiplicity.Value == ModelConstants.Multiplicity_Many && otherEnd.Multiplicity.Value == ModelConstants.Multiplicity_Many)) { // and the association's foreign key is on the TPH side (ergo, the association is mapped to the same table as the TPH hierarchy) if (tphTable == associationSetMappingTable) { return(true); } } } } return(false); }
protected override void OnTypeDescriptorInitialize() { base.OnTypeDescriptorInitialize(); if (TypedEFElement != null) { var ends = TypedEFElement.AssociationEnds(); if (ends.Count > 0) { end1 = ends[0]; var et1 = end1.Type.Target; var cet1 = et1 as ConceptualEntityType; if (cet1 != null) { navProp1 = cet1.FindNavigationPropertyForEnd(end1); } } if (ends.Count > 1) { end2 = ends[1]; var et2 = end2.Type.Target; var cet2 = et2 as ConceptualEntityType; if (cet2 != null) { navProp2 = cet2.FindNavigationPropertyForEnd(end2); } } _ref = new ReferentialConstraintProperty(); } }
public override int GetHashCode() { unchecked { return((base.GetHashCode() * 397) ^ (AssociationEnd != null ? AssociationEnd.GetHashCode() : 0)); } }
/// <summary> /// Get navigate result for specified associaion type and end /// </summary> /// <param name="associationType">The association type.</param> /// <param name="toEnd">The end to navigate to.</param> /// <returns>The result query entity value(s) for navigate.</returns> public QueryValue GetNavigateResult(AssociationType associationType, AssociationEnd toEnd) { ExceptionUtilities.Assert(this.navigateResultLookup.ContainsKey(associationType), "Invalid AssociationType for Navigate: {0}", associationType.FullName); var lookupBasedOnEnd = this.navigateResultLookup[associationType]; ExceptionUtilities.Assert(lookupBasedOnEnd.ContainsKey(toEnd), "Invalid ToEnd for Navigate: {0}.{1}, from {2}.", associationType.FullName, toEnd.RoleName, (this.Type as QueryEntityType).EntityType.FullName); return(lookupBasedOnEnd[toEnd]); }
/// <summary> /// Creates new OnDeleteAction for AssociationEnd or changes existing one /// </summary> /// <param name="end"></param> /// <param name="action"></param> internal CreateOnDeleteActionCommand(AssociationEnd end, string action) { CommandValidation.ValidateAssociationEnd(end); ValidateString(action); _parentEnd = end; _action = action; }
public void RemoveEnd(AssociationEnd end) { associationEnds.Remove(end); if (!associationEnds.Contains(end)) { end.Class.Assocations.Remove(this); } }
private static string GetEndRole(AssociationEnd end) { if (end == null) { return(String.Empty); } return(end.Role.Value); }
public void RemoveAssociationEnd(AssociationEnd end) { RemoveAssociationEndCommmand removeAssociationEndCommmand = (RemoveAssociationEndCommmand)RemoveAssociationEndCommmandFactory.Factory().Create(DiagramController.ModelController); removeAssociationEndCommmand.AssociationEnd = end; removeAssociationEndCommmand.Execute(); }
private static void SetEndRole(AssociationEnd end, string value) { var cpc = PropertyWindowViewModelHelper.GetCommandProcessorContext(); Command c = new ChangeAssociationEndCommand(end, null, value); var cp = new CommandProcessor(cpc, c); cp.Invoke(); }
public string GetAssociationReturn(AssociationEnd association) { if (association.IsCollection()) { return(String.Format("{0} ?? ({0} = new {1}())", association.Name().ToPrivateMember(), association.ConstructorType())); } return(association.Name().ToPrivateMember()); }
private static string GetEndMultiplicity(AssociationEnd end) { if (end == null) { return(String.Empty); } return(end.Multiplicity.Value); }
public void AddCheckConstraint(AssociationEnd associationEnd) { string checkFunc = null; if (associationEnd.MaxMultiplicity == "1" && associationEnd.MinMultiplicity == "1") { checkFunc = associationEnd.Name().ToPascalCase() + " != null"; } else if (associationEnd.MaxMultiplicity == "*") { checkFunc = associationEnd.Name().ToPascalCase() + ".Count >= " + associationEnd.MinMultiplicity; } else { checkFunc = string.Format("{0}.Count >= {1} && {0}.Count <= {2}", associationEnd.Name().ToPascalCase(), associationEnd.MinMultiplicity, associationEnd.MaxMultiplicity); } #line default #line hidden #line 157 "C:\Dev\Intent.Modules\Modules\Intent.Modules.RichDomain\Templates\EntityState\DomainEntityStateTemplate.tt" this.Write(" RequiredMultiplcityChecks[\""); #line default #line hidden #line 158 "C:\Dev\Intent.Modules\Modules\Intent.Modules.RichDomain\Templates\EntityState\DomainEntityStateTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(associationEnd.Name().ToPascalCase())); #line default #line hidden #line 158 "C:\Dev\Intent.Modules\Modules\Intent.Modules.RichDomain\Templates\EntityState\DomainEntityStateTemplate.tt" this.Write("\"] = () => "); #line default #line hidden #line 158 "C:\Dev\Intent.Modules\Modules\Intent.Modules.RichDomain\Templates\EntityState\DomainEntityStateTemplate.tt" this.Write(this.ToStringHelper.ToStringWithCulture(checkFunc)); #line default #line hidden #line 158 "C:\Dev\Intent.Modules\Modules\Intent.Modules.RichDomain\Templates\EntityState\DomainEntityStateTemplate.tt" this.Write(" ;\r\n"); #line default #line hidden #line 159 "C:\Dev\Intent.Modules\Modules\Intent.Modules.RichDomain\Templates\EntityState\DomainEntityStateTemplate.tt" }
public void ChangeRole(AssociationEnd end, string role) { RenameElementCommand <AssociationEnd> command = (RenameElementCommand <AssociationEnd>) RenameElementCommandFactory <AssociationEnd> .Factory().Create(DiagramController.ModelController); command.NewName = role; command.RenamedElement = end; command.AssociatedElements.Add(Association); command.Execute(); }
public void ChangeAggregation(AssociationEnd end, AggregationKind newAggregation) { ChangeAssociationAggregationCommand associationAggregationCommand = (ChangeAssociationAggregationCommand)ChangeAssociationAggregationCommandFactory.Factory().Create(DiagramController.ModelController); associationAggregationCommand.AssociationEnd = end; associationAggregationCommand.NewAggregationKind = newAggregation; associationAggregationCommand.Execute(); }
private static string GetEndOnDelete(AssociationEnd end) { if (end != null && end.OnDeleteAction != null) { return(end.OnDeleteAction.Action.Value); } return(ModelConstants.OnDeleteAction_None); }
public string CreateForeignKeyPropertyIfApplicable(AssociationEnd association) { if (association.RelationshipType == RelationshipType.OneToMany) { return(string.Format("public Guid{0} {1}Id ", association.IsMandatory() ? "" : "?", association.Name().ToPascalCase()) + "{ get; set; }"); } return(String.Empty); }
public static string ConstructorType(this AssociationEnd associationEnd) { if (associationEnd.IsCollection()) { return("List<" + associationEnd.Class.Name + ">"); } return(associationEnd.Class.Name); }
public AssociationEndViewHelper(Diagram diagram, AssociationViewHelper associationViewHelper, AssociationEnd associationEnd) : base(diagram) { AssociationViewHelper = associationViewHelper; MultiplicityLabelViewHelper = new AssociationLabelViewHelper(diagram); RoleLabelViewHelper = new AssociationLabelViewHelper(diagram); AssociationEnd = associationEnd; points = new ObservablePointCollection(); }
public static string IdentifierName(this AssociationEnd associationEnd) { if (string.IsNullOrEmpty(associationEnd.Role)) { return(associationEnd.Class.IdentifierType()); } else { return(StringExtensions.ToPascalCase(associationEnd.Role) + "Id");// associationEnd.Class.IdentifierType(); } }
private XElement GenerateAssociationEnd(XNamespace xmlNamespace, AssociationEnd end) { return(new XElement( xmlNamespace + "End", new XAttribute("Role", end.RoleName), new XAttribute("Type", this.GetFullyQualifiedName(end.EntityType)), new XAttribute("Multiplicity", this.GetMultiplicityString(end.Multiplicity)), this.GenerateDocumentation(xmlNamespace, end), this.GenerateOnDelete(end, xmlNamespace), this.GenerateAnnotations(xmlNamespace, end))); }
/// <summary> /// Initializes a new instance of the <see cref="PIM_AssociationEnd"/> class. /// </summary> /// <param name="xCaseCanvas">canvas where the control is placed</param> /// <param name="viewHelper">ViewHelper of the control, stores visualization information.</param> /// <param name="associationEnd">reprsented association end.</param> public PIM_AssociationEnd(XCaseCanvas xCaseCanvas, AssociationEndViewHelper viewHelper, AssociationEnd associationEnd) : base(xCaseCanvas) { PositionChanged += AdjustLabelsPositions; AssociationEnd = associationEnd; ViewHelper = viewHelper; if (multiplicityLabel != null) { multiplicityLabel.ViewHelper = ViewHelper.MultiplicityLabelViewHelper; } }
public void ChangeMultiplicity(AssociationEnd end, string newCardinality) { uint? lower; UnlimitedNatural upper; if (!MultiplicityElementController.ParseMultiplicityString(newCardinality, out lower, out upper)) { return; } MultiplicityElementController.ChangeMultiplicityOfElement(end, Association, lower, upper, DiagramController.ModelController); }
internal void SetNavigateResult(AssociationType associationType, AssociationEnd toEnd, QueryValue result) { if (!this.navigateResultLookup.ContainsKey(associationType)) { this.navigateResultLookup.Add(associationType, new Dictionary <AssociationEnd, QueryValue>()); } Dictionary <AssociationEnd, QueryValue> lookupBasedOnEnd = this.navigateResultLookup[associationType]; lookupBasedOnEnd[toEnd] = result; }
public string DeterminePrinciple(AssociationEnd associationEnd) { if (associationEnd.AssociationType == AssociationType.Composite || associationEnd.OtherAssociationEnd().AssociationType == AssociationType.Aggregation) { return("Principal"); } if (associationEnd.AssociationType == AssociationType.Aggregation || associationEnd.OtherAssociationEnd().AssociationType == AssociationType.Composite) { return("Dependent"); } return(""); }
/// <summary> /// Creates a ReferentialConstraint in the association that is the parent of the principal /// End. /// </summary> /// <param name="principalEnd"></param> /// <param name="dependentEnd"></param> /// <param name="principalProperties"></param> /// <param name="dependentProperties"></param> internal CreateReferentialConstraintCommand( AssociationEnd principalEnd, AssociationEnd dependentEnd, IEnumerable <Property> principalProperties, IEnumerable <Property> dependentProperties) { CommandValidation.ValidateAssociationEnd(principalEnd); CommandValidation.ValidateAssociationEnd(dependentEnd); PrincipalEnd = principalEnd; DependentEnd = dependentEnd; PrincipalProperties = principalProperties; DependentProperties = dependentProperties; }
/// <summary> /// Creates a ReferentialConstraint in the association that is the parent of the principal /// End. /// </summary> /// <param name="principalEnd"></param> /// <param name="dependentEnd"></param> /// <param name="principalProperties"></param> /// <param name="dependentProperties"></param> internal CreateReferentialConstraintCommand( AssociationEnd principalEnd, AssociationEnd dependentEnd, IEnumerable<Property> principalProperties, IEnumerable<Property> dependentProperties) { CommandValidation.ValidateAssociationEnd(principalEnd); CommandValidation.ValidateAssociationEnd(dependentEnd); PrincipalEnd = principalEnd; DependentEnd = dependentEnd; PrincipalProperties = principalProperties; DependentProperties = dependentProperties; }
private XElement GenerateReferentialEnd(string endTypeName, AssociationEnd end, IEnumerable <MemberProperty> properties, XNamespace xmlNamespace) { var propRefs = from p in properties select new XElement( xmlNamespace + "PropertyRef", new XAttribute("Name", p.Name)); return(new XElement( xmlNamespace + endTypeName, new XAttribute("Role", end.RoleName), propRefs)); }
private XElement GenerateOnDelete(AssociationEnd end, XNamespace xmlNamespace) { if (end.DeleteBehavior == OperationAction.Cascade) { return(new XElement( xmlNamespace + "OnDelete", new XAttribute("Action", "Cascade"))); } else { return(null); } }
internal CreateNavigationPropertyCommand( string name, ConceptualEntityType entity, Association association, AssociationEnd end1, AssociationEnd end2) { if (string.IsNullOrEmpty(name)) { throw new ArgumentNullException("name"); } if (entity == null) { throw new ArgumentNullException("entity"); } Name = name; Entity = entity; Association = association; FromEnd = end1; ToEnd = end2; }
private static bool DoesEndNeedCondition(AssociationEnd end, AssociationEnd otherEnd, EntityType associationSetMappingTable) { if (end.Multiplicity.Value == ModelConstants.Multiplicity_ZeroOrOne) { return true; } var cet = end.Type.Target as ConceptualEntityType; Debug.Assert(end.Type.Target != null ? cet != null : true, "EntityType is not a ConceptualEntityType"); if (cet != null && cet.HasResolvableBaseType) { // the subtype is mapped using TPH EntityType tphTable = null; if (IsMappedUsingTph(cet, out tphTable)) { // the association is not *:* if (!(end.Multiplicity.Value == ModelConstants.Multiplicity_Many && otherEnd.Multiplicity.Value == ModelConstants.Multiplicity_Many)) { // and the association's foreign key is on the TPH side (ergo, the association is mapped to the same table as the TPH hierarchy) if (tphTable == associationSetMappingTable) { return true; } } } } return false; }
private AssociationEnd ReadAssociationEndElement(XmlElement xmlElement, XmlNamespaceManager nsmgr, Dictionary<string, ModelBase> elementIndex) { var result = new AssociationEnd(); SetById(elementIndex, xmlElement, result); result.Name = xmlElement.Attributes["name"].ValueOr(null); if (String.IsNullOrWhiteSpace(result.Name)) result.Name = null; result.Visibility = xmlElement.Attributes["visibility"].ValueOr("public"); result.Aggregation = xmlElement.Attributes["aggregation"].ValueOr("none"); resolvers.Add((ix) => result.Type = GetById(ix, xmlElement.Attributes["type"].ValueOr(null)) as IModelType); var mul = xmlElement.SelectSingleNode("UML:AssociationEnd.multiplicity/UML:Multiplicity/UML:Multiplicity.range/UML:MultiplicityRange", nsmgr); if (mul != null) result.Multiplicity = mul.Attributes["lower"].ValueOr("0") + ".." + mul.Attributes["upper"].ValueOr("-1").Replace("-1", "*"); return result; }
internal static void ValidateAssociationEnd(AssociationEnd end) { ValidateEFElement(end); }
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 assocation 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; }
/// <summary> /// Creates a command of that can change an AssociationEnd /// </summary> /// <param name="end">The end to change</param> /// <param name="multiplicity">Changes the end's multiplicity, this may end up adding or removing conditions on any AssociationSetMappings</param> /// <param name="role">Changes the Role property of the end</param> internal ChangeAssociationEndCommand(AssociationEnd end, string multiplicity, string role) { End = end; Multiplicity = multiplicity; Role = role; }
internal AssociationEnd GetOtherEnd(AssociationEnd oneEnd) { return End1 == oneEnd ? End2 : End1; }
protected override void InvokeInternal(CommandProcessorContext cpc) { _property.Relationship.SetRefName(_association); _property.Relationship.Rebind(); Debug.Assert( (_property.Relationship.Status == BindingStatus.Known || (_association == null && _property.Relationship.Status == BindingStatus.Undefined)), "Rebind for the NavigationProperty failed"); if (_association != null) { if (_end1 == null || _end2 == null) { var associationEnds = _association.AssociationEnds(); Debug.Assert(associationEnds.Count < 3, "AssociationEnds are >= 3"); _end1 = associationEnds.Where( r => r.Type != null && r.Type.Status == BindingStatus.Known && r.Type.Target == _property.Parent) .FirstOrDefault(); _end2 = associationEnds.Where( r => r.Type != null && r.Type.Status == BindingStatus.Known && ((r.Type.Target != _property.Parent) || (r.Type.Target == _property.Parent && r != _end1))).FirstOrDefault(); } // updating association's multiplicity value as opposed to multiplicity itself. if (string.IsNullOrEmpty(_multiplicity) && _end2 != null) { _multiplicity = _end2.Multiplicity.Value; } } else { // resets end points when we get a null association _end1 = null; _end2 = null; } // rebinds association properties. _property.FromRole.SetRefName(_end1); _property.FromRole.Rebind(); _property.ToRole.SetRefName(_end2); _property.ToRole.Rebind(); if (_property.ToRole.Status == BindingStatus.Known && string.Compare(_property.ToRole.Target.Multiplicity.Value, _multiplicity, StringComparison.OrdinalIgnoreCase) != 0) { if (_property.Relationship.Status == BindingStatus.Known) { var association = _property.Relationship.Target; _property.ToRole.Target.Multiplicity.Value = _multiplicity; if (association != null && association.AssociationSet != null && association.AssociationSet.AssociationSetMapping != null) { EnforceAssociationSetMappingRules.AddRule(cpc, association.AssociationSet.AssociationSetMapping); } } } }
internal override bool ParseSingleElement(ICollection<XName> unprocessedElements, XElement elem) { if (elem.Name.LocalName == AssociationEnd.ElementName) { var assocEnd = new AssociationEnd(this, elem); _ends.Add(assocEnd); assocEnd.Parse(unprocessedElements); } else if (elem.Name.LocalName == ReferentialConstraint.ElementName) { if (_referentialConstraint != null) { var msg = String.Format( CultureInfo.CurrentCulture, Resources.TOO_MANY_REFERENTIAL_CONSTRAINTS_IN_ASSOCIATION, LocalName.Value); Artifact.AddParseErrorForObject(this, msg, ErrorCodes.TOO_MANY_REFERENTIAL_CONSTRAINTS_IN_ASSOCIATION); } else { _referentialConstraint = new ReferentialConstraint(this, elem); _referentialConstraint.Parse(unprocessedElements); } } else { return base.ParseSingleElement(unprocessedElements, elem); } return true; }
private void cmdPrincipalRole_SelectedIndexChanged(object sender, EventArgs e) { AssociationEnd principal = null; AssociationEnd dependent = null; if (cmdPrincipalRole.SelectedItem == _roleListItems[_end1]) { principal = _end1; dependent = _end2; } else if (cmdPrincipalRole.SelectedItem == _roleListItems[_end2]) { principal = _end2; dependent = _end1; } if (principal == _principal) { return; // no change } // remember new choice _principal = principal; _dependent = dependent; if (_dependent == null) { txtDependentRole.Text = string.Empty; } else { txtDependentRole.Text = _dependent.Role.Value; } // clear our lists listMappings.Items.Clear(); _mappingListItems.Clear(); cmbDependentKey.Items.Clear(); _dependentListItems.Clear(); // user might have chosen the blank row if (_principal != null && _dependent != null) { PopulateMappingListItems(); PopulateListView(); listMappings.Enabled = true; // load dependent role keys into the combo box if (_dependent.Type.Target != null) { cmbDependentKey.Items.Add(_blankDependentKeyListItem); foreach (var key in GetMappableDependentProperties()) { var item = new KeyListItem(key.NormalizedName); _dependentListItems.Add(key.NormalizedName, item); cmbDependentKey.Items.Add(item); } // in the SSDL, ref constraints can be to non-key columns if (_association.EntityModel.IsCSDL == false) { foreach (var prop in _dependent.Type.Target.Properties()) { if (prop.IsKeyProperty) { continue; } var item = new KeyListItem(prop.NormalizedName); _dependentListItems.Add(prop.NormalizedName, item); cmbDependentKey.Items.Add(item); } } } cmbDependentKey.Enabled = true; // select the first row if (listMappings.Items.Count > 0) { listMappings.Focus(); var lvItem = listMappings.Items[0]; lvItem.Selected = true; ShowDependencyKeyComboBox(lvItem); } } else { listMappings.Enabled = false; cmbDependentKey.Enabled = false; ChangeDependencyKeyComboBoxVisibility(false); } }
internal ReferentialConstraintDialog(Association association) { if (association == null) { // this should never be null on current code-paths. throw new ArgumentNullException("association"); } _association = association; _end1 = _association.AssociationEnds()[0]; _end2 = _association.AssociationEnds()[1]; var selfAssociation = (_end1.Type.Target == _end2.Type.Target); _roleListItems.Add(_end1, new RoleListItem(_end1, selfAssociation)); _roleListItems.Add(_end2, new RoleListItem(_end2, selfAssociation)); InitializeComponent(); // enable tool tips listMappings.ShowItemToolTips = true; if (EdmFeatureManager.GetForeignKeysInModelFeatureState(association.Artifact.SchemaVersion).IsEnabled()) { hdrDepedent.Text = DialogsResource.RefConstraintDialog_DependentKeyHeader_SupportFKs; } // Set the default font to VS shell font. var vsFont = VSHelpers.GetVSFont(Services.ServiceProvider); if (vsFont != null) { Font = vsFont; } // load list of roles cmdPrincipalRole.Items.Add(_blankRoleListItem); cmdPrincipalRole.Items.Add(_roleListItems[_end1]); cmdPrincipalRole.Items.Add(_roleListItems[_end2]); }
internal RoleListItem(AssociationEnd end, bool useRoleName) { _end = end; _useRoleName = useRoleName; }
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> /// Determines whether we should create an Association in the existing artifact given /// the ReferentialConstraint and AssociationEnd info from the temp artifact /// </summary> private static bool ShouldCreateAssociationGivenReferentialConstraint( ReferentialConstraint refConstraintInTempArtifact, AssociationEnd end1InTempArtifact, AssociationEnd end2InTempArtifact, ConceptualEntityType end1EntityTypeInExistingArtifact, ConceptualEntityType end2EntityTypeInExistingArtifact, out bool end1IsPrincipalEnd, out List<Property> principalPropertiesInExistingArtifact, out List<Property> dependentPropertiesInExistingArtifact, out List<string> unfoundPrincipalProperties, out List<string> unfoundDependentProperties) { end1IsPrincipalEnd = true; principalPropertiesInExistingArtifact = new List<Property>(); unfoundPrincipalProperties = new List<string>(); dependentPropertiesInExistingArtifact = new List<Property>(); unfoundDependentProperties = new List<string>(); ConceptualEntityType principalEndEntityType = null; ConceptualEntityType dependentEndEntityType = null; if (refConstraintInTempArtifact == null) { Debug.Fail("Should not have null ReferentialConstraint"); // no ReferentialConstraint in temp artifact to clone return false; } // determine which end is principal and which dependent if (refConstraintInTempArtifact.Principal.Role.Target == end1InTempArtifact) { Debug.Assert( refConstraintInTempArtifact.Dependent.Role.Target == end2InTempArtifact, "Unexpected end value for Dependent Role of ReferentialConstraint when Principal Role matches end1 from temp artifact"); end1IsPrincipalEnd = true; principalEndEntityType = end1EntityTypeInExistingArtifact; dependentEndEntityType = end2EntityTypeInExistingArtifact; } else if (refConstraintInTempArtifact.Principal.Role.Target == end2InTempArtifact) { Debug.Assert( refConstraintInTempArtifact.Dependent.Role.Target == end1InTempArtifact, "Unexpected end value for Dependent Role of ReferentialConstraint when Principal Role matches end2 from temp artifact"); end1IsPrincipalEnd = false; principalEndEntityType = end2EntityTypeInExistingArtifact; dependentEndEntityType = end1EntityTypeInExistingArtifact; } else { Debug.Fail("Couldn't identify principal & dependent end"); return false; } // find the principal properties in the existing doc to include in the referential constraint foreach (var tempProp in refConstraintInTempArtifact.Principal.Properties) { var prop = FindMatchingPropertyInExistingArtifactEntityType(tempProp, principalEndEntityType); if (prop != null) { principalPropertiesInExistingArtifact.Add(prop); } else { unfoundPrincipalProperties.Add(tempProp.LocalName.Value); } } // find the dependent properties in the existing doc to include in the referential constraint foreach (var tempProp in refConstraintInTempArtifact.Dependent.Properties) { var prop = FindMatchingPropertyInExistingArtifactEntityType(tempProp, dependentEndEntityType); if (prop != null) { dependentPropertiesInExistingArtifact.Add(prop); } else { unfoundDependentProperties.Add(tempProp.LocalName.Value); } } // return true if we found matching properties for all the properties in // both the principal and dependent ends, false otherwise if (unfoundDependentProperties.Count == 0 && unfoundPrincipalProperties.Count == 0) { return true; } else { return false; } }
internal void AddAssociationEnd(AssociationEnd end) { _ends.Add(end); }
/// <summary> /// Clone the Association with its ReferentialConstraint (if available), AssociationSet /// and AssociationSetMapping. If the ReferentialConstraint is available in the temp artifact /// but we cannot find matching properties in the existing artifact then the whole Association /// (and AssociationSet and AssociationSetMapping) will not be cloned, a warning message will /// be issued but otherwise the process is not stopped. /// But if the Association cannot be created for any other reason that's an error and an /// UpdateModelFromDatabaseException will be thrown. /// </summary> /// <param name="cpc">CommandProcessorContext for the commands to be issued</param> /// <param name="existingArtifact">the existing artifact in which to make these changes</param> /// <param name="assocInTempArtifact">the Association in the temp artifact to be cloned</param> /// <param name="end1InTempArtifact">the end of the Association in the temp artifact to be cloned to be treated as End1</param> /// <param name="end2InTempArtifact">the end of the Association in the temp artifact to be cloned to be treated as End2</param> /// <param name="navProp1InTempArtifact">the NavigationProperty for End1 in the temp artifact to be cloned</param> /// <param name="navProp2InTempArtifact">the NavigationProperty for End2 in the temp artifact to be cloned</param> /// <param name="end1EntityTypeInExistingArtifact">the EntityType in the existing artifact matching the End1 target in the temp artifact</param> /// <param name="end2EntityTypeInExistingArtifact">the EntityType in the existing artifact matching the End2 target in the temp artifact</param> /// <param name="tempArtifactCEntityTypeToNewCEntityTypeInExistingArtifact"> /// a Dictionary mapping temp artifact EntityTypes which have /// been identified as new to their equivalent in the existing artifact /// </param> private void CloneAssociation( CommandProcessorContext cpc, EFArtifact existingArtifact, Association assocInTempArtifact, AssociationEnd end1InTempArtifact, AssociationEnd end2InTempArtifact, NavigationProperty navProp1InTempArtifact, NavigationProperty navProp2InTempArtifact, ConceptualEntityType end1EntityTypeInExistingArtifact, ConceptualEntityType end2EntityTypeInExistingArtifact, Dictionary<EntityType, EntityType> tempArtifactCEntityTypeToNewCEntityTypeInExistingArtifact) { Association newAssocInExistingArtifact = null; AssociationEnd newAssocEnd1 = null; AssociationEnd newAssocEnd2 = null; if (assocInTempArtifact.ReferentialConstraint == null) { // if there is no ReferentialConstraint to clone then just try to // create the Association and AssociationSet var cmd = new CreateConceptualAssociationCommand( assocInTempArtifact.LocalName.Value, end1EntityTypeInExistingArtifact, end1InTempArtifact.Multiplicity.Value, navProp1InTempArtifact.LocalName.Value, end2EntityTypeInExistingArtifact, end2InTempArtifact.Multiplicity.Value, navProp2InTempArtifact.LocalName.Value, true, false); CommandProcessor.InvokeSingleCommand(cpc, cmd); newAssocInExistingArtifact = cmd.CreatedAssociation; newAssocEnd1 = cmd.End1; newAssocEnd2 = cmd.End2; } else { // There is a ReferentialConstraint - so we need to check whether we can find matching properties // for the Principal and Dependent roles of the ReferentialConstraint. If we can't find // matching properties then log a warning message and return. Otherwise attempt to create // the Association (and its AssociationSet) followed by a matching ReferentialConstraint. // // Note: ShouldCreateAssociationGivenReferentialConstraint() produces 2 sets of information: // (1) the sets of matching properties to use if we can find matching properties for the Principal // and Dependent roles, and (2) the sets of property names to include in the error message if // we cannot find matching properties for the Principal and Dependent roles. // If ShouldCreateAssociationGivenReferentialConstraint() returns true we use the first set of // information to create the ReferentialConstraint after having created the Association and // AssociationSet. If it returns false we use the second set of information to construct the // warning message. var refConstraintInTempArtifact = assocInTempArtifact.ReferentialConstraint; bool end1IsPrincipalEnd; List<Property> principalPropertiesInExistingArtifact; List<Property> dependentPropertiesInExistingArtifact; List<string> unfoundPrincipalProperties; List<string> unfoundDependentProperties; if (ShouldCreateAssociationGivenReferentialConstraint( refConstraintInTempArtifact, end1InTempArtifact, end2InTempArtifact, end1EntityTypeInExistingArtifact, end2EntityTypeInExistingArtifact, out end1IsPrincipalEnd, out principalPropertiesInExistingArtifact, out dependentPropertiesInExistingArtifact, out unfoundPrincipalProperties, out unfoundDependentProperties)) { // create the new Association and AssociationSet var cmd = new CreateConceptualAssociationCommand( assocInTempArtifact.LocalName.Value, end1EntityTypeInExistingArtifact, end1InTempArtifact.Multiplicity.Value, navProp1InTempArtifact.LocalName.Value, end2EntityTypeInExistingArtifact, end2InTempArtifact.Multiplicity.Value, navProp2InTempArtifact.LocalName.Value, true, false); CommandProcessor.InvokeSingleCommand(cpc, cmd); newAssocInExistingArtifact = cmd.CreatedAssociation; newAssocEnd1 = cmd.End1; newAssocEnd2 = cmd.End2; // Add in the ReferentialConstraint for the new Association if (null != newAssocInExistingArtifact) { AddReferentialConstraintForAssociation( cpc, cmd, end1IsPrincipalEnd, principalPropertiesInExistingArtifact, dependentPropertiesInExistingArtifact); } } else { // Unable to find matching properties for the Principal and Dependent roles of // the ReferentialConstraint. So log a warning message. newAssocInExistingArtifact = null; EntityType principalEndEntityType = end1IsPrincipalEnd ? end1EntityTypeInExistingArtifact : end2EntityTypeInExistingArtifact; EntityType dependentEndEntityType = end1IsPrincipalEnd ? end2EntityTypeInExistingArtifact : end1EntityTypeInExistingArtifact; LogWarningMessageForReferentialConstraintProperties( assocInTempArtifact.LocalName.Value, principalEndEntityType, dependentEndEntityType, unfoundPrincipalProperties, unfoundDependentProperties); // having logged the warning message we do not need to attempt to create // the AssociationSetMapping nor throw an exception due to the lack of the // created Association - so just return return; } } // if we have failed to create an Association at this stage that's a serious error // so throw an exception to indicate the failure if (null == newAssocInExistingArtifact) { throw new UpdateModelFromDatabaseException( string.Format( CultureInfo.CurrentCulture, Resources.UpdateFromDatabaseCannotCreateAssociation, assocInTempArtifact.ToPrettyString())); } // update OnDeleteActions to match temp artifact UpdateOnDeleteAction(cpc, newAssocEnd1, end1InTempArtifact); UpdateOnDeleteAction(cpc, newAssocEnd2, end2InTempArtifact); // add a new AssociationSetMapping for the new Association AddAssociationSetMappingForConceptualAssociation( cpc, existingArtifact, assocInTempArtifact, newAssocInExistingArtifact, tempArtifactCEntityTypeToNewCEntityTypeInExistingArtifact); }
private static void UpdateOnDeleteAction(CommandProcessorContext cpc, AssociationEnd newAssocEnd, AssociationEnd tempArtifactAssocEnd) { Debug.Assert(newAssocEnd != null, "newAssoc should not be null"); Debug.Assert(tempArtifactAssocEnd != null, "tempArtifactAssocEnd should not be null"); if (newAssocEnd == null || tempArtifactAssocEnd == null) { return; } // ensure the OnDeleteAction for the existing artifact is the same as that for the temp artifact if (null == tempArtifactAssocEnd.OnDeleteAction && null != newAssocEnd.OnDeleteAction) { // temp artifact has no OnDeleteAction - so delete the one in the existing artifact newAssocEnd.OnDeleteAction.Delete(); } else if (null != tempArtifactAssocEnd.OnDeleteAction && null != tempArtifactAssocEnd.OnDeleteAction.Action) { var tempArtifactOnDeleteAction = tempArtifactAssocEnd.OnDeleteAction.Action.Value; if (null == newAssocEnd.OnDeleteAction) { // existing artifact has no OnDeleteAction - so create a new one and assign the value from the temp artifact var cmd = new CreateOnDeleteActionCommand(newAssocEnd, tempArtifactOnDeleteAction); CommandProcessor.InvokeSingleCommand(cpc, cmd); } // use ordinal comparison as possible values for this attribute are fixed regardless of locale else if (false == newAssocEnd.OnDeleteAction.Action.Value.Equals(tempArtifactOnDeleteAction, StringComparison.Ordinal)) { // existing artifact has an OnDeleteAction but the value does not match - so assign the value from the temp artifact var cmd = new UpdateDefaultableValueCommand<string>(newAssocEnd.OnDeleteAction.Action, tempArtifactOnDeleteAction); CommandProcessor.InvokeSingleCommand(cpc, cmd); } } }