/// <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;
                    }
                }
            }
        }
        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
 }
예제 #14
0
 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);
        }
예제 #17
0
 internal static void ValidateNavigationProperty(NavigationProperty navigationProperty)
 {
     ValidateEFElement(navigationProperty);
 }