/// <summary> /// Creates a FunctionScalarProperty element (potentially within multiple ComplexProperty elements) that /// maps the Property at the bottom of the passed in property chain to the passed in Parameter /// within the passed in ModificationFunction. /// </summary> /// <param name="modificationFunction">ultimate parent for ScalarProperty created by this</param> /// <param name="propertyChain">property to be inserted, preceded by its ComplexProperty parents if appropriate</param> /// <param name="navPropPointingToProperty"> /// Optional - if present indicates the Scalar Property at /// the bottom of the propertyChain was reached via a NavProp (propertyChain will have only 1 Property) /// </param> /// <param name="parameter">The sproc parameter to which we will map</param> internal CreateFunctionScalarPropertyTreeCommand( ModificationFunction modificationFunction, List<Property> propertyChain, NavigationProperty navPropPointingToProperty, Parameter parameter, string version) { CommandValidation.ValidateModificationFunction(modificationFunction); CommandValidation.ValidateParameter(parameter); if (null != navPropPointingToProperty) { CommandValidation.ValidateNavigationProperty(navPropPointingToProperty); } Debug.Assert(propertyChain.Count > 0, "Properties list should contain at least one element"); _modificationFunction = modificationFunction; _propertyChain = propertyChain; _navPropPointingToProperty = navPropPointingToProperty; if (_navPropPointingToProperty != null) { Debug.Assert( propertyChain.Count == 1, "When creating a FunctionScalarProperty via a NavigationProperty propertyChain should have only 1 element, but it has " + propertyChain.Count); } _parameter = parameter; Debug.Assert( string.IsNullOrEmpty(version) || ModelConstants.FunctionScalarPropertyVersionOriginal.Equals(version, StringComparison.Ordinal) || ModelConstants.FunctionScalarPropertyVersionCurrent.Equals(version, StringComparison.Ordinal), "version should be empty or " + ModelConstants.FunctionScalarPropertyVersionOriginal + " or " + ModelConstants.FunctionScalarPropertyVersionCurrent + ". Actual value: " + version); _version = version; }
/// <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; }
/// <summary> /// Sets facets on the passed in property /// </summary> /// <param name="property">Must be a non-null conceptual property</param> /// <param name="getterAccessModifier">Optional facet</param> /// <param name="setterAccessModifier">Optional facet</param> internal SetNavigationPropertyFacetsCommand(NavigationProperty property, string getterAccessModifier, string setterAccessModifier) { CommandValidation.ValidateNavigationProperty(property); _property = property; _getterAccessModifier = getterAccessModifier; _setterAccessModifier = setterAccessModifier; }
/// <summary> /// Creates a command of that can change a Navigation Property /// </summary> /// <param name="association">The association to use.</param> /// <param name="property">The navigation property to change</param> internal ChangeNavigationPropertyCommand(NavigationProperty property, Association association) { if (property == null) { throw new ArgumentNullException("property"); } _property = property; _association = association; }
protected override void InvokeInternal(CommandProcessorContext cpc) { // we allow the command to set null _endpoints if needed. var navProp1 = new NavigationProperty(Entity, null); navProp1.LocalName.Value = Name; navProp1.Relationship.SetRefName(Association); navProp1.FromRole.SetRefName(FromEnd); navProp1.ToRole.SetRefName(ToEnd); Entity.AddNavigationProperty(navProp1); _createdNavigationProperty = navProp1; XmlModelHelper.NormalizeAndResolve(navProp1); }
/// <summary> /// Creates a command of that can change a Navigation Property /// </summary> /// <param name="property">The navigation property to change</param> /// <param name="association">The association to use.</param> /// <param name="multiplicity">Changes the end's multiplicity, this may end up adding or removing conditions on any AssociationSetMappings</param> internal ChangeNavigationPropertyCommand(NavigationProperty property, Association association, string multiplicity) { if (property == null) { throw new ArgumentNullException("property"); } if (association == null) { throw new ArgumentNullException("association"); } if (string.IsNullOrEmpty(multiplicity)) { throw new ArgumentNullException("multiplicity"); } _property = property; _association = association; _multiplicity = multiplicity; }
/// <summary> /// Creates a ScalarProperty element that maps the passed in Property to the Parameter, inside /// the parent ModificationFunction. /// </summary> /// <param name="property"></param> /// <param name="navPropPointingToProperty"></param> /// <param name="parm"></param> /// <param name="version">Optional</param> internal CreateFunctionScalarPropertyCommand( ModificationFunction parentModificationFunction, Property property, NavigationProperty navPropPointingToProperty, Parameter parm, string version) { CommandValidation.ValidateProperty(property); CommandValidation.ValidateParameter(parm); CommandValidation.ValidateModificationFunction(parentModificationFunction); // we don't require a non-null navigation property since the function scalar property could exist // directly in its parent if (navPropPointingToProperty != null) { CommandValidation.ValidateNavigationProperty(navPropPointingToProperty); } _property = property; _pointingNavProperty = navPropPointingToProperty; _parm = parm; _version = version; _parentModFunc = parentModificationFunction; }
internal NavigationPropertyClipboardFormat(NavigationProperty property) : base(property) { _relationship = _fromRole = _toRole = String.Empty; Debug.Assert( property != null, "Null property is passed in to NavigationPropertyClipboardFormat constructor."); if (property != null) { // Navigation property might not have corresponding association. if (property.Relationship != null && property.Relationship.Target != null) { _relationship = property.Relationship.Target.LocalName.Value; Debug.Assert( property.FromRole != null, "Navigation Property's FromRole attribute should not be null if the property's association is set. Property Name:" + property.DisplayName + ", Association name: " + property.Relationship.ToPrettyString()); if (property.FromRole != null) { _fromRole = property.FromRole.RefName; } Debug.Assert( property.ToRole != null, "Navigation Property's ToRole attribute should not be null if the property's association is set. Property Name:" + property.DisplayName + ", Association name: " + property.Relationship.ToPrettyString()); if (property.ToRole != null) { _toRole = property.ToRole.RefName; } } } }
/// <summary> /// Change the property pointed to by the FunctionScalarProperty. This may involve /// change of property chain, change to/from a NavProp property or change of parameter. /// </summary> /// <param name="fspToChange">FunctionScalarProperty to be changed</param> /// <param name="newPropertiesChain">property chain for new Property</param> /// <param name="newPointingNavProp">NavProp for new Property (null indicates new Property not reached via NavProp)</param> /// <param name="newParameter">Parameter to which new Property should be mapped (null indicates use existing Parameter)</param> /// <param name="newVersion">Version attribute for new Property (null indicates use existing value). Only appropriate for Update Functions</param> internal ChangeFunctionScalarPropertyCommand( FunctionScalarProperty fspToChange, List<Property> newPropertiesChain, NavigationProperty newPointingNavProp, Parameter newParameter, string newVersion) { Debug.Assert( !(newPropertiesChain == null && newPointingNavProp == null && newParameter == null), "Not all of newPropertiesChain, newPointingNavProp, newParameter can be null"); if (newPropertiesChain == null && newPointingNavProp == null && newParameter == null) { return; } Debug.Assert( string.IsNullOrEmpty(newVersion) || ModelConstants.FunctionScalarPropertyVersionOriginal.Equals(newVersion, StringComparison.Ordinal) || ModelConstants.FunctionScalarPropertyVersionCurrent.Equals(newVersion, StringComparison.Ordinal), "newVersion must be empty or " + ModelConstants.FunctionScalarPropertyVersionOriginal + " or " + ModelConstants.FunctionScalarPropertyVersionCurrent + ". Actual value: " + newVersion); CommandValidation.ValidateFunctionScalarProperty(fspToChange); if (newPointingNavProp != null) { CommandValidation.ValidateNavigationProperty(newPointingNavProp); } if (newParameter != null) { CommandValidation.ValidateParameter(newParameter); } _existingFunctionScalarProperty = fspToChange; _propChain = newPropertiesChain; _pointingNavProp = newPointingNavProp; _param = newParameter; _version = newVersion; }
/// <summary> /// Creates a ScalarProperty element that maps the passed in Property to the Parameter, inside /// the ComplexProperty given by the passed in CreateFunctionComplexPropertyCommand pre-req Command. /// </summary> /// <param name="prereq"></param> /// <param name="property"></param> /// <param name="navPropPointingToProperty"></param> /// <param name="parm"></param> /// <param name="version">Optional</param> internal CreateFunctionScalarPropertyCommand( CreateFunctionComplexPropertyCommand prereq, Property property, NavigationProperty navPropPointingToProperty, Parameter parm, string version) : base(PrereqId) { ValidatePrereqCommand(prereq); CommandValidation.ValidateProperty(property); CommandValidation.ValidateParameter(parm); // we don't require a non-null navigation property since the function scalar property could exist // directly in its parent if (navPropPointingToProperty != null) { CommandValidation.ValidateNavigationProperty(navPropPointingToProperty); } _property = property; _pointingNavProperty = navPropPointingToProperty; _parm = parm; _version = version; _parentModFunc = null; // parent should be a ComplexProperty from the prereq Command AddPreReqCommand(prereq); }
/// <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); }
public ExplorerNavigationProperty(EditingContext context, NavigationProperty navigationProperty, ExplorerEFElement parent) : base(context, navigationProperty, parent) { // do nothing }
internal void AddNavigationProperty(NavigationProperty navProp) { _navigationProperties.Add(navProp); }
internal void SetNavigationProperty(NavigationProperty navProp) { _pointingNavProperty = navProp; }
internal static FunctionScalarProperty CreateFunctionScalarPropertyInAssociationEnd( ModificationFunction mf, Property entityProperty, NavigationProperty pointingNavProperty, Parameter parm, string version) { // in creating the function scalar property, we modify the AssociationEnd depending on the navigation property that is // pointing to the actual property. If we don't have this navigation property we can't do anything. Debug.Assert( pointingNavProperty != null, "We need the navigation property pointing to the property in order to create the mapping function scalar property"); if (pointingNavProperty == null) { throw new CannotLocateReferencedItemException(); } Debug.Assert(pointingNavProperty.Relationship.Target != null, "Where is the Association for this navigation property?"); if (pointingNavProperty.Relationship.Target == null) { throw new CannotLocateReferencedItemException(); } var assocSet = pointingNavProperty.Relationship.Target.AssociationSet; var navPropFromEnd = pointingNavProperty.FromRole.Target; var navPropToEnd = pointingNavProperty.ToRole.Target; Debug.Assert(null != navPropFromEnd, "Null FromRole for pointingNavProperty " + pointingNavProperty.ToPrettyString()); Debug.Assert(null != navPropToEnd, "Null ToRole for pointingNavProperty " + pointingNavProperty.ToPrettyString()); AssociationSetEnd assocSetFromEnd = null; AssociationSetEnd assocSetToEnd = null; // figure which end is which // Note: it is valid for the NavigationProperty to point to // an EntityType in the same inheritance hierarchy foreach (var end in assocSet.AssociationSetEnds()) { if (end.Role.Target == navPropFromEnd) { Debug.Assert( null == assocSetFromEnd, "pointingNavProperty From End " + navPropFromEnd.ToPrettyString() + " matches more than 1 AssociationSetEnd for AssociationSet " + assocSet.ToPrettyString()); assocSetFromEnd = end; } else if (end.Role.Target == navPropToEnd) { Debug.Assert( null == assocSetToEnd, "pointingNavProperty To End " + navPropToEnd.ToPrettyString() + " matches more than 1 AssociationSetEnd for AssociationSet " + assocSet.ToPrettyString()); assocSetToEnd = end; } } Debug.Assert(null != assocSetFromEnd, "Cannot find From end of AssociationSet " + assocSet.ToPrettyString()); Debug.Assert(null != assocSetToEnd, "Cannot find To end of AssociationSet " + assocSet.ToPrettyString()); // see if we already have this AssociationEnd FunctionAssociationEnd fae = null; foreach (var funcAssocEnd in mf.AssociationEnds()) { if (funcAssocEnd.AssociationSet.Target == assocSet && funcAssocEnd.From.Target == assocSetFromEnd && funcAssocEnd.To.Target == assocSetToEnd) { fae = funcAssocEnd; break; } } // create the association end if needed if (fae == null) { fae = new FunctionAssociationEnd(mf, null); fae.AssociationSet.SetRefName(assocSet); fae.From.SetRefName(assocSetFromEnd); fae.To.SetRefName(assocSetToEnd); mf.AddAssociationEnd(fae); XmlModelHelper.NormalizeAndResolve(fae); } Debug.Assert(fae != null, "Failed to create the AssocationEnd to house this ScalarProperty"); if (fae == null) { throw new ParentItemCreationFailureException(); } // create the SP inside this return CreateFunctionScalarPropertyCommon(fae, entityProperty, parm, version); }
internal static void ValidateNavigationProperty(NavigationProperty navigationProperty) { ValidateEFElement(navigationProperty); }