示例#1
0
        public static void AdjustEFCoreProperties(PropertyDescriptorCollection propertyDescriptors, Association element)
        {
            //ModelRoot modelRoot = element.Source.ModelRoot;

            //for (int index = 0; index < propertyDescriptors.Count; index++)
            //{
            //   bool shouldRemove = false;
            //   switch (propertyDescriptors[index].Name)
            //   {

            //      default:
            //         break;
            //   }

            //   if (shouldRemove)
            //      propertyDescriptors.Remove(propertyDescriptors[index--]);
            //}
        }
        internal static bool SetEndpointRoles(Association element)
        {
            switch (element.TargetMultiplicity)
            {
            case Multiplicity.ZeroMany:

                switch (element.SourceMultiplicity)
                {
                case Multiplicity.ZeroMany:
                    element.SourceRole = EndpointRole.NotApplicable;
                    element.TargetRole = EndpointRole.NotApplicable;

                    return(true);

                case Multiplicity.One:
                    element.SourceRole = EndpointRole.Principal;
                    element.TargetRole = EndpointRole.Dependent;

                    return(true);

                case Multiplicity.ZeroOne:
                    element.SourceRole = EndpointRole.Principal;
                    element.TargetRole = EndpointRole.Dependent;

                    return(true);
                }

                break;

            case Multiplicity.One:

                switch (element.SourceMultiplicity)
                {
                case Multiplicity.ZeroMany:
                    element.SourceRole = EndpointRole.Dependent;
                    element.TargetRole = EndpointRole.Principal;

                    return(true);

                case Multiplicity.One:

                    return(false);

                case Multiplicity.ZeroOne:
                    element.SourceRole = EndpointRole.Dependent;
                    element.TargetRole = EndpointRole.Principal;

                    return(true);
                }

                break;

            case Multiplicity.ZeroOne:

                switch (element.SourceMultiplicity)
                {
                case Multiplicity.ZeroMany:
                    element.SourceRole = EndpointRole.Dependent;
                    element.TargetRole = EndpointRole.Principal;

                    return(true);

                case Multiplicity.One:
                    element.SourceRole = EndpointRole.Principal;
                    element.TargetRole = EndpointRole.Dependent;

                    return(true);

                case Multiplicity.ZeroOne:

                    return(false);
                }

                break;
            }

            return(false);
        }
        /// <inheritdoc />
        public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e)
        {
            base.ElementPropertyChanged(e);

            Association element = (Association)e.ModelElement;

            if (element.IsDeleted)
            {
                return;
            }

            Store       store   = element.Store;
            Transaction current = store.TransactionManager.CurrentTransaction;

            if (current.IsSerializing || ModelRoot.BatchUpdating)
            {
                return;
            }

            if (Equals(e.NewValue, e.OldValue))
            {
                return;
            }

            List <string>            errorMessages            = EFCoreValidator.GetErrors(element).ToList();
            BidirectionalAssociation bidirectionalAssociation = element as BidirectionalAssociation;

            using (Transaction inner = store.TransactionManager.BeginTransaction("Redraw Association"))
            {
                switch (e.DomainProperty.Name)
                {
                case "FKPropertyName":
                {
                    string fkPropertyName  = e.NewValue?.ToString();
                    bool   fkPropertyError = false;

                    // these can be multiples, separated by a comma
                    string[] priorForeignKeyPropertyNames = e.OldValue?.ToString().Split(',').Select(n => n.Trim()).ToArray() ?? new string[0];

                    IEnumerable <ModelAttribute> priorForeignKeyModelAttributes = string.IsNullOrEmpty(e.OldValue?.ToString())
                                                                                        ? Array.Empty <ModelAttribute>()
                                                                                        : priorForeignKeyPropertyNames
                                                                                  .Select(oldValue => element.Dependent.Attributes.FirstOrDefault(a => a.Name == oldValue))
                                                                                  .Where(x => x != null)
                                                                                  .ToArray();

                    string summaryBoilerplate = element.GetSummaryBoilerplate();

                    if (!string.IsNullOrEmpty(fkPropertyName))
                    {
                        string tag = $"({element.Source.Name}:{element.Target.Name})";

                        if (element.Dependent == null)
                        {
                            errorMessages.Add($"{tag} can't have foreign keys defined; no dependent role found");

                            break;
                        }

                        string[] foreignKeyPropertyNames = element.GetForeignKeyPropertyNames();
                        int      propertyCount           = foreignKeyPropertyNames.Length;
                        int      identityCount           = element.Principal.AllIdentityAttributes.Count();

                        if (propertyCount != identityCount)
                        {
                            errorMessages.Add($"{tag} foreign key must have zero or {identityCount} {(identityCount == 1 ? "property" : "properties")} defined, since "
                                              + $"{element.Principal.Name} has {identityCount} identity properties; found {propertyCount} instead");

                            fkPropertyError = true;
                        }

                        // validate names
                        foreach (string propertyName in foreignKeyPropertyNames)
                        {
                            if (!CodeGenerator.IsValidLanguageIndependentIdentifier(propertyName))
                            {
                                errorMessages.Add($"{tag} FK property name '{propertyName}' isn't a valid .NET identifier");
                                fkPropertyError = true;
                            }

                            if (element.Dependent.AllAttributes.Except(element.Dependent.Attributes).Any(a => a.Name == propertyName))
                            {
                                errorMessages.Add($"{tag} FK property name '{propertyName}' is used in a base class of {element.Dependent.Name}");
                                fkPropertyError = true;
                            }
                        }

                        fkPropertyError &= CheckFkAutoIdentityErrors(element, errorMessages);

                        if (!fkPropertyError)
                        {
                            // remove any flags and locks on the attributes that were foreign keys
                            foreach (ModelAttribute modelAttribute in priorForeignKeyModelAttributes)
                            {
                                modelAttribute.ClearFKData(summaryBoilerplate);
                            }

                            element.EnsureForeignKeyAttributes();

                            IEnumerable <ModelAttribute> currentForeignKeyModelAttributes = foreignKeyPropertyNames.Select(newValue => element.Dependent.Attributes.FirstOrDefault(a => a.Name == newValue));

                            foreach (ModelAttribute modelAttribute in currentForeignKeyModelAttributes)
                            {
                                modelAttribute.SetFKData(summaryBoilerplate);
                            }
                        }
                    }
                    else
                    {
                        // foreign key was removed
                        // remove locks
                        foreach (ModelAttribute modelAttribute in priorForeignKeyModelAttributes)
                        {
                            modelAttribute.ClearFKData(summaryBoilerplate);
                        }
                    }
                }

                break;

                case "SourceCustomAttributes":

                    if (bidirectionalAssociation != null && !string.IsNullOrWhiteSpace(bidirectionalAssociation.SourceCustomAttributes))
                    {
                        bidirectionalAssociation.SourceCustomAttributes = $"[{bidirectionalAssociation.SourceCustomAttributes.Trim('[', ']')}]";
                        CheckSourceForDisplayText(bidirectionalAssociation);
                    }

                    break;

                case "SourceDisplayText":

                    if (bidirectionalAssociation != null)
                    {
                        CheckSourceForDisplayText(bidirectionalAssociation);
                    }

                    break;

                case "SourceMultiplicity":
                    Multiplicity sourceMultiplicity = (Multiplicity)e.NewValue;

                    // change unidirectional source cardinality
                    // if target is dependent
                    //    source cardinality is 0..1 or 1
                    if (element.Target.IsDependentType && sourceMultiplicity == Multiplicity.ZeroMany)
                    {
                        errorMessages.Add($"Can't have a 0..* association from {element.Target.Name} to dependent type {element.Source.Name}");

                        break;
                    }

                    if ((sourceMultiplicity == Multiplicity.One && element.TargetMultiplicity == Multiplicity.One) ||
                        (sourceMultiplicity == Multiplicity.ZeroOne && element.TargetMultiplicity == Multiplicity.ZeroOne))
                    {
                        if (element.SourceRole != EndpointRole.NotSet)
                        {
                            element.SourceRole = EndpointRole.NotSet;
                        }

                        if (element.TargetRole != EndpointRole.NotSet)
                        {
                            element.TargetRole = EndpointRole.NotSet;
                        }
                    }
                    else
                    {
                        SetEndpointRoles(element);
                    }

                    // cascade delete behavior could now be illegal. Reset to default
                    element.SourceDeleteAction = DeleteAction.Default;
                    element.TargetDeleteAction = DeleteAction.Default;

                    break;

                case "SourcePropertyName":
                    string sourcePropertyNameErrorMessage = ValidateAssociationIdentifier(element, element.Target, (string)e.NewValue);

                    if (EFModelDiagram.IsDropping && sourcePropertyNameErrorMessage != null)
                    {
                        element.Delete();
                    }
                    else
                    {
                        errorMessages.Add(sourcePropertyNameErrorMessage);
                    }

                    break;

                case "SourceRole":

                    if (element.Source.IsDependentType)
                    {
                        element.SourceRole = EndpointRole.Dependent;
                        element.TargetRole = EndpointRole.Principal;
                    }
                    else if (!SetEndpointRoles(element))
                    {
                        if (element.SourceRole == EndpointRole.Dependent && element.TargetRole != EndpointRole.Principal)
                        {
                            element.TargetRole = EndpointRole.Principal;
                        }
                        else if (element.SourceRole == EndpointRole.Principal && element.TargetRole != EndpointRole.Dependent)
                        {
                            element.TargetRole = EndpointRole.Dependent;
                        }
                    }

                    break;

                case "TargetCustomAttributes":

                    if (!string.IsNullOrWhiteSpace(element.TargetCustomAttributes))
                    {
                        element.TargetCustomAttributes = $"[{element.TargetCustomAttributes.Trim('[', ']')}]";
                        CheckTargetForDisplayText(element);
                    }

                    break;

                case "TargetDisplayText":

                    CheckTargetForDisplayText(element);

                    break;

                case "TargetMultiplicity":
                    Multiplicity newTargetMultiplicity = (Multiplicity)e.NewValue;

                    // change unidirectional target cardinality
                    // if target is dependent
                    //    target cardinality must be 0..1 or 1
                    if (element.Target.IsDependentType && newTargetMultiplicity == Multiplicity.ZeroMany)
                    {
                        errorMessages.Add($"Can't have a 0..* association from {element.Source.Name} to dependent type {element.Target.Name}");

                        break;
                    }

                    if ((element.SourceMultiplicity == Multiplicity.One && newTargetMultiplicity == Multiplicity.One) ||
                        (element.SourceMultiplicity == Multiplicity.ZeroOne && newTargetMultiplicity == Multiplicity.ZeroOne))
                    {
                        if (element.SourceRole != EndpointRole.NotSet)
                        {
                            element.SourceRole = EndpointRole.NotSet;
                        }

                        if (element.TargetRole != EndpointRole.NotSet)
                        {
                            element.TargetRole = EndpointRole.NotSet;
                        }
                    }
                    else
                    {
                        SetEndpointRoles(element);
                    }

                    // cascade delete behavior could now be illegal. Reset to default
                    element.SourceDeleteAction = DeleteAction.Default;
                    element.TargetDeleteAction = DeleteAction.Default;

                    break;

                case "TargetPropertyName":

                    // if we're creating an association via drag/drop, it's possible the existing property name
                    // is the same as the default property name. The default doesn't get created until the transaction is
                    // committed, so the drop's action will cause a name clash. Remove the clashing property, but
                    // only if drag/drop.

                    string targetPropertyNameErrorMessage = ValidateAssociationIdentifier(element, element.Source, (string)e.NewValue);

                    if (EFModelDiagram.IsDropping && targetPropertyNameErrorMessage != null)
                    {
                        element.Delete();
                    }
                    else
                    {
                        errorMessages.Add(targetPropertyNameErrorMessage);
                    }

                    break;

                case "TargetRole":

                    if (element.Target.IsDependentType)
                    {
                        element.SourceRole = EndpointRole.Principal;
                        element.TargetRole = EndpointRole.Dependent;
                    }
                    else if (!SetEndpointRoles(element))
                    {
                        if (element.TargetRole == EndpointRole.Dependent && element.SourceRole != EndpointRole.Principal)
                        {
                            element.SourceRole = EndpointRole.Principal;
                        }
                        else if (element.TargetRole == EndpointRole.Principal && element.SourceRole != EndpointRole.Dependent)
                        {
                            element.SourceRole = EndpointRole.Dependent;
                        }
                    }

                    break;
                }


                element.RedrawItem();
                inner.Commit();
            }

            errorMessages = errorMessages.Where(m => m != null).ToList();

            if (errorMessages.Any())
            {
                current.Rollback();
                ErrorDisplay.Show(string.Join("\n", errorMessages));
            }
        }
        public override void ElementAdded(ElementAddedEventArgs e)
        {
            base.ElementAdded(e);

            Association          element = (Association)e.ModelElement;
            Store                store   = element.Store;
            Transaction          current = store.TransactionManager.CurrentTransaction;
            PluralizationService pluralizationService = ModelRoot.PluralizationService;

            if (current.IsSerializing)
            {
                return;
            }

            // add unidirectional
            //    source can't be dependent (connection builder handles this)
            // if target is dependent,
            //    source cardinality is 0..1
            //    target cardinality is 0..1
            //    source is principal
            if (element is UnidirectionalAssociation && element.Target.IsDependentType)
            {
                element.TargetMultiplicity = Multiplicity.ZeroOne;
                element.SourceRole         = EndpointRole.Principal;
                element.TargetRole         = EndpointRole.Dependent;
            }

            // add bidirectional
            //    neither can be dependent (connection builder handles this)

            if (string.IsNullOrEmpty(element.TargetPropertyName))
            {
                string rootName = element.TargetMultiplicity == Multiplicity.ZeroMany && pluralizationService?.IsSingular(element.Target.Name) == true
                                 ? pluralizationService.Pluralize(element.Target.Name)
                                 : element.Target.Name;

                string identifierName = rootName;
                int    index          = 0;

                while (element.Source.HasPropertyNamed(identifierName))
                {
                    identifierName = $"{rootName}_{++index}";
                }

                element.TargetPropertyName = identifierName;
            }

            if (element is BidirectionalAssociation bidirectionalAssociation)
            {
                if (string.IsNullOrEmpty(bidirectionalAssociation.SourcePropertyName))
                {
                    string rootName = element.SourceMultiplicity == Multiplicity.ZeroMany && pluralizationService?.IsSingular(element.Source.Name) == true
                                    ? pluralizationService.Pluralize(element.Source.Name)
                                    : element.Source.Name;

                    string identifierName = rootName;
                    int    index          = 0;

                    while (element.Target.HasPropertyNamed(identifierName))
                    {
                        identifierName = $"{rootName}_{++index}";
                    }

                    bidirectionalAssociation.SourcePropertyName = identifierName;
                }
            }

            AssociationChangeRules.SetEndpointRoles(element);
        }
示例#5
0
 /// <summary>
 ///    Method to set IsTargetImplementNotifyTracking to false so that this instance of this tracking property is not
 ///    storage-based.
 /// </summary>
 /// <param name="element">
 ///    The element on which to reset the property value.
 /// </param>
 internal void PreResetValue(Association element)
 {
     // Force the IsTargetImplementNotifyTracking property to false so that the value
     // of the TargetImplementNotify property is retrieved from storage.
     element.isTargetImplementNotifyTrackingPropertyStorage = false;
 }
示例#6
0
        public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e)
        {
            base.ElementPropertyChanged(e);

            ModelClass element = (ModelClass)e.ModelElement;

            if (element.IsDeleted)
            {
                return;
            }

            Store       store   = element.Store;
            Transaction current = store.TransactionManager.CurrentTransaction;

            if (current.IsSerializing)
            {
                return;
            }

            if (Equals(e.NewValue, e.OldValue))
            {
                return;
            }

            List <string> errorMessages = EFCoreValidator.GetErrors(element).ToList();

            switch (e.DomainProperty.Name)
            {
            case "DbSetName":
            {
                string newDbSetName = (string)e.NewValue;

                if (element.IsDependentType)
                {
                    if (!string.IsNullOrEmpty(newDbSetName))
                    {
                        element.DbSetName = string.Empty;
                    }
                }
                else
                {
                    if (string.IsNullOrEmpty(newDbSetName))
                    {
                        element.DbSetName = MakeDefaultName(element.Name);
                    }

                    if (current.Name.ToLowerInvariant() != "paste" &&
                        (string.IsNullOrWhiteSpace(newDbSetName) || !CodeGenerator.IsValidLanguageIndependentIdentifier(newDbSetName)))
                    {
                        errorMessages.Add($"DbSet name '{newDbSetName}' isn't a valid .NET identifier.");
                    }
                    else if (store.Get <ModelClass>()
                             .Except(new[] { element })
                             .Any(x => x.DbSetName == newDbSetName))
                    {
                        errorMessages.Add($"DbSet name '{newDbSetName}' already in use");
                    }
                }

                break;
            }

            case "ImplementNotify":
            {
                bool newImplementNotify = (bool)e.NewValue;

                if (newImplementNotify)
                {
                    List <string> nameList = element.Attributes.Where(x => x.AutoProperty).Select(x => x.Name).ToList();
                    if (nameList.Any())
                    {
                        string names = nameList.Count > 1
                                       ? string.Join(", ", nameList.Take(nameList.Count - 1)) + " and " + nameList.Last()
                                       : nameList.First();

                        string verb = nameList.Count > 1
                                      ? "is an autoproperty"
                                      : "are autoproperties";

                        WarningDisplay.Show($"{names} {verb}, so will not participate in INotifyPropertyChanged messages");
                    }
                }

                PresentationHelper.UpdateClassDisplay(element);

                break;
            }

            case "IsAbstract":
            {
                bool newIsAbstract = (bool)e.NewValue;

                if (newIsAbstract && element.IsDependentType)
                {
                    errorMessages.Add($"Can't make {element.Name} abstract since it's a dependent type");

                    break;
                }

                PresentationHelper.UpdateClassDisplay(element);

                break;
            }

            case "IsDependentType":
            {
                bool newIsDependentType = (bool)e.NewValue;

                if (newIsDependentType)
                {
                    if (element.IsAbstract)
                    {
                        errorMessages.Add($"Can't make {element.Name} a dependent class since it's abstract");

                        break;
                    }

                    // dependent type can't be source in an association
                    if (store.Get <UnidirectionalAssociation>()
                        .Any(a => a.Source == element))
                    {
                        errorMessages.Add($"Can't make {element.Name} a dependent class since it references other classes");

                        break;
                    }

                    if (store.Get <BidirectionalAssociation>()
                        .Any(a => a.Source == element || a.Target == element))
                    {
                        errorMessages.Add($"Can't make {element.Name} a dependent class since it's in a bidirectional association");

                        break;
                    }

                    if (store.Get <Association>()
                        .Any(a => a.Target == element && a.TargetMultiplicity == Multiplicity.ZeroMany))
                    {
                        errorMessages.Add($"Can't make {element.Name} a dependent class since it's the target of a 0..* association");

                        break;
                    }

                    foreach (ModelAttribute modelAttribute in element.AllAttributes.Where(a => a.IsIdentity))
                    {
                        modelAttribute.IsIdentity = false;
                    }

                    foreach (UnidirectionalAssociation association in Association.GetLinksToTargets(element).OfType <UnidirectionalAssociation>())
                    {
                        if (association.SourceMultiplicity == Multiplicity.ZeroMany)
                        {
                            association.SourceMultiplicity = Multiplicity.ZeroOne;
                        }

                        if (association.TargetMultiplicity == Multiplicity.ZeroMany)
                        {
                            association.TargetMultiplicity = Multiplicity.ZeroOne;
                        }

                        association.TargetRole = EndpointRole.Dependent;
                    }

                    element.TableName = string.Empty;
                    element.DbSetName = string.Empty;
                }
                else
                {
                    element.DbSetName = MakeDefaultName(element.Name);
                    element.TableName = MakeDefaultName(element.Name);
                }

                PresentationHelper.UpdateClassDisplay(element);

                break;
            }

            case "Name":
            {
                string newName = (string)e.NewValue;

                if (current.Name.ToLowerInvariant() != "paste" &&
                    (string.IsNullOrWhiteSpace(newName) || !CodeGenerator.IsValidLanguageIndependentIdentifier(newName)))
                {
                    errorMessages.Add($"Class name '{newName}' isn't a valid .NET identifier.");
                }

                else if (store.ElementDirectory
                         .AllElements
                         .OfType <ModelClass>()
                         .Except(new[] { element })
                         .Any(x => x.Name == newName))
                {
                    errorMessages.Add($"Class name '{newName}' already in use by another class");
                }

                else if (store.ElementDirectory
                         .AllElements
                         .OfType <ModelEnum>()
                         .Any(x => x.Name == newName))
                {
                    errorMessages.Add($"Class name '{newName}' already in use by an enum");
                }

                else if (!string.IsNullOrEmpty((string)e.OldValue))
                {
                    string oldDefaultName = MakeDefaultName((string)e.OldValue);
                    string newDefaultName = MakeDefaultName(newName);

                    if (element.DbSetName == oldDefaultName)
                    {
                        element.DbSetName = newDefaultName;
                    }

                    if (element.TableName == oldDefaultName)
                    {
                        element.TableName = newDefaultName;
                    }
                }

                break;
            }

            case "Namespace":
            {
                string newNamespace = (string)e.NewValue;

                if (current.Name.ToLowerInvariant() != "paste")
                {
                    errorMessages.Add(CommonRules.ValidateNamespace(newNamespace, CodeGenerator.IsValidLanguageIndependentIdentifier));
                }

                break;
            }

            case "TableName":
            {
                string newTableName = (string)e.NewValue;

                if (element.IsDependentType)
                {
                    if (!string.IsNullOrEmpty(newTableName))
                    {
                        element.TableName = string.Empty;
                    }
                }
                else
                {
                    if (string.IsNullOrEmpty(newTableName))
                    {
                        element.TableName = MakeDefaultName(element.Name);
                    }

                    if (store.Get <ModelClass>()
                        .Except(new[] { element })
                        .Any(x => x.TableName == newTableName))
                    {
                        errorMessages.Add($"Table name '{newTableName}' already in use");
                    }
                }

                break;
            }
            }

            errorMessages = errorMessages.Where(m => m != null).ToList();

            if (errorMessages.Any())
            {
                current.Rollback();
                ErrorDisplay.Show(string.Join("\n", errorMessages));
            }
        }
        internal static void SetEndpointRoles(Association element)
        {
            switch (element.TargetMultiplicity)
            {
            case Multiplicity.ZeroMany:
                switch (element.SourceMultiplicity)
                {
                case Multiplicity.ZeroMany:
                    element.SourceRole = EndpointRole.NotApplicable;
                    element.TargetRole = EndpointRole.NotApplicable;
                    break;

                case Multiplicity.One:
                    element.SourceRole = EndpointRole.Principal;
                    element.TargetRole = EndpointRole.Dependent;
                    break;

                case Multiplicity.ZeroOne:
                    element.SourceRole = EndpointRole.Principal;
                    element.TargetRole = EndpointRole.Dependent;
                    break;
                }

                break;

            case Multiplicity.One:
                switch (element.SourceMultiplicity)
                {
                case Multiplicity.ZeroMany:
                    element.SourceRole = EndpointRole.Dependent;
                    element.TargetRole = EndpointRole.Principal;
                    break;

                case Multiplicity.One:
                    break;

                case Multiplicity.ZeroOne:
                    element.SourceRole = EndpointRole.Dependent;
                    element.TargetRole = EndpointRole.Principal;
                    break;
                }

                break;

            case Multiplicity.ZeroOne:
                switch (element.SourceMultiplicity)
                {
                case Multiplicity.ZeroMany:
                    element.SourceRole = EndpointRole.Dependent;
                    element.TargetRole = EndpointRole.Principal;
                    break;

                case Multiplicity.One:
                    element.SourceRole = EndpointRole.Principal;
                    element.TargetRole = EndpointRole.Dependent;
                    break;

                case Multiplicity.ZeroOne:
                    break;
                }

                break;
            }
        }
        public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e)
        {
            base.ElementPropertyChanged(e);

            Association element   = (Association)e.ModelElement;
            Store       store     = element.Store;
            Transaction current   = store.TransactionManager.CurrentTransaction;
            ModelRoot   modelRoot = store.ElementDirectory.FindElements <ModelRoot>().FirstOrDefault();

            if (current.IsSerializing)
            {
                return;
            }

            List <string> errorMessages = EFCoreValidator.GetErrors(element).ToList();

            switch (e.DomainProperty.Name)
            {
            case "Persistent":
                UpdateDisplayForPersistence(element);
                break;

            case "TargetPropertyName":
                errorMessages.Add(ValidateAssociationIdentifier(element, element.Source, element.Target, (string)e.NewValue));
                break;

            case "SourcePropertyName":
                errorMessages.Add(ValidateAssociationIdentifier(element, element.Target, element.Source, (string)e.NewValue));
                break;

            case "SourceMultiplicity":
                Multiplicity newSourceMultiplicity = (Multiplicity)e.NewValue;

                if ((newSourceMultiplicity == Multiplicity.One && element.TargetMultiplicity == Multiplicity.One) ||
                    (newSourceMultiplicity == Multiplicity.ZeroOne && element.TargetMultiplicity == Multiplicity.ZeroOne))
                {
                    element.SourceRole = EndpointRole.NotSet;
                    element.TargetRole = EndpointRole.NotSet;
                }
                else
                {
                    SetEndpointRoles(element);
                }

                UpdateDisplayForCascadeDelete(element, null, null, newSourceMultiplicity);
                break;

            case "TargetMultiplicity":
                Multiplicity newTargetMultiplicity = (Multiplicity)e.NewValue;

                if ((element.SourceMultiplicity == Multiplicity.One && newTargetMultiplicity == Multiplicity.One) ||
                    (element.SourceMultiplicity == Multiplicity.ZeroOne && newTargetMultiplicity == Multiplicity.ZeroOne))
                {
                    element.SourceRole = EndpointRole.NotSet;
                    element.TargetRole = EndpointRole.NotSet;
                }
                else
                {
                    SetEndpointRoles(element);
                }

                UpdateDisplayForCascadeDelete(element, null, null, null, newTargetMultiplicity);
                break;

            case "SourceRole":
                EndpointRole newSourceRole = (EndpointRole)e.NewValue;
                if (element.TargetRole == EndpointRole.NotSet && newSourceRole == EndpointRole.Dependent)
                {
                    element.TargetRole = EndpointRole.Principal;
                }
                else if (element.TargetRole == EndpointRole.NotSet && newSourceRole == EndpointRole.Principal)
                {
                    element.TargetRole = EndpointRole.Dependent;
                }

                break;

            case "TargetRole":
                EndpointRole newTargetRole = (EndpointRole)e.NewValue;
                if (element.SourceRole == EndpointRole.NotSet && newTargetRole == EndpointRole.Dependent)
                {
                    element.SourceRole = EndpointRole.Principal;
                }
                else if (element.SourceRole == EndpointRole.NotSet && newTargetRole == EndpointRole.Principal)
                {
                    element.SourceRole = EndpointRole.Dependent;
                }

                break;

            case "SourceDeleteAction":
                DeleteAction sourceDeleteAction = (DeleteAction)e.NewValue;
                UpdateDisplayForCascadeDelete(element, sourceDeleteAction);

                break;

            case "TargetDeleteAction":
                DeleteAction targetDeleteAction = (DeleteAction)e.NewValue;
                UpdateDisplayForCascadeDelete(element, null, targetDeleteAction);
                break;
            }

            errorMessages = errorMessages.Where(m => m != null).ToList();
            if (errorMessages.Any())
            {
                current.Rollback();
                MessageBox.Show(string.Join("; ", errorMessages));
            }
        }
示例#9
0
        public static void AdjustEFCoreProperties(PropertyDescriptorCollection propertyDescriptors, Association element)
        {
            ModelRoot modelRoot = element.Source.ModelRoot;

            for (int index = 0; index < propertyDescriptors.Count; index++)
            {
                bool shouldRemove = false;
                switch (propertyDescriptors[index].Name)
                {
                case "TargetPersistencePoint":
                    shouldRemove = element.TargetAutoProperty || modelRoot.EntityFrameworkVersion == EFVersion.EF6;
                    break;

                case "SourcePersistencePoint":
                    if (element is BidirectionalAssociation bidirectionalAssociation)
                    {
                        shouldRemove = bidirectionalAssociation.SourceAutoProperty || modelRoot.EntityFrameworkVersion == EFVersion.EF6;
                    }
                    break;

                default:
                    break;
                }

                if (shouldRemove)
                {
                    propertyDescriptors.Remove(propertyDescriptors[index--]);
                }
            }
        }
示例#10
0
        public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e)
        {
            base.ElementPropertyChanged(e);

            Association element = (Association)e.ModelElement;
            Store       store   = element.Store;
            Transaction current = store.TransactionManager.CurrentTransaction;

            if (current.IsSerializing)
            {
                return;
            }

            if (Equals(e.NewValue, e.OldValue))
            {
                return;
            }

            List <string> errorMessages = EFCoreValidator.GetErrors(element).ToList();

            switch (e.DomainProperty.Name)
            {
            case "Persistent":
                UpdateDisplayForPersistence(element);
                break;

            case "SourceDeleteAction":
                DeleteAction sourceDeleteAction = (DeleteAction)e.NewValue;
                UpdateDisplayForCascadeDelete(element, sourceDeleteAction);

                break;

            case "SourceMultiplicity":
                Multiplicity sourceMultiplicity = (Multiplicity)e.NewValue;

                // change unidirectional source cardinality
                // if target is dependent
                //    source cardinality is 0..1 or 1
                if (element.Target.IsDependentType && sourceMultiplicity == Multiplicity.ZeroMany)
                {
                    errorMessages.Add($"Can't have a 0..* association from {element.Target.Name} to dependent type {element.Source.Name}");

                    break;
                }

                if ((sourceMultiplicity == Multiplicity.One && element.TargetMultiplicity == Multiplicity.One) ||
                    (sourceMultiplicity == Multiplicity.ZeroOne && element.TargetMultiplicity == Multiplicity.ZeroOne))
                {
                    if (element.SourceRole != EndpointRole.NotSet)
                    {
                        element.SourceRole = EndpointRole.NotSet;
                    }
                    if (element.TargetRole != EndpointRole.NotSet)
                    {
                        element.TargetRole = EndpointRole.NotSet;
                    }
                }
                else
                {
                    SetEndpointRoles(element);
                }

                UpdateDisplayForCascadeDelete(element, null, null, sourceMultiplicity);
                break;

            case "SourcePropertyName":
                string sourcePropertyNameErrorMessage = ValidateAssociationIdentifier(element, element.Target, (string)e.NewValue);
                if (EFModelDiagram.IsDropping && sourcePropertyNameErrorMessage != null)
                {
                    element.Delete();
                }
                else
                {
                    errorMessages.Add(sourcePropertyNameErrorMessage);
                }
                break;

            case "SourceRole":
                if (element.Source.IsDependentType)
                {
                    element.SourceRole = EndpointRole.Dependent;
                    element.TargetRole = EndpointRole.Principal;
                }
                else
                {
                    EndpointRole sourceRole = (EndpointRole)e.NewValue;

                    if (sourceRole == EndpointRole.Dependent && element.TargetRole != EndpointRole.Principal)
                    {
                        element.TargetRole = EndpointRole.Principal;
                    }
                    else if (sourceRole == EndpointRole.Principal && element.TargetRole != EndpointRole.Dependent)
                    {
                        element.TargetRole = EndpointRole.Dependent;
                    }
                    SetEndpointRoles(element);
                }

                break;

            case "TargetDeleteAction":
                DeleteAction targetDeleteAction = (DeleteAction)e.NewValue;
                UpdateDisplayForCascadeDelete(element, null, targetDeleteAction);
                break;

            case "TargetMultiplicity":
                Multiplicity newTargetMultiplicity = (Multiplicity)e.NewValue;

                // change unidirectional target cardinality
                // if target is dependent
                //    target cardinality must be 0..1 or 1
                if (element.Target.IsDependentType && newTargetMultiplicity == Multiplicity.ZeroMany)
                {
                    errorMessages.Add($"Can't have a 0..* association from {element.Source.Name} to dependent type {element.Target.Name}");

                    break;
                }

                if ((element.SourceMultiplicity == Multiplicity.One && newTargetMultiplicity == Multiplicity.One) ||
                    (element.SourceMultiplicity == Multiplicity.ZeroOne && newTargetMultiplicity == Multiplicity.ZeroOne))
                {
                    if (element.SourceRole != EndpointRole.NotSet)
                    {
                        element.SourceRole = EndpointRole.NotSet;
                    }
                    if (element.TargetRole != EndpointRole.NotSet)
                    {
                        element.TargetRole = EndpointRole.NotSet;
                    }
                }
                else
                {
                    SetEndpointRoles(element);
                }

                UpdateDisplayForCascadeDelete(element, null, null, null, newTargetMultiplicity);
                break;

            case "TargetPropertyName":
                // if we're creating an association via drag/drop, it's possible the existing property name
                // is the same as the default property name. The default doesn't get created until the transaction is
                // committed, so the drop's action will cause a name clash. Remove the clashing property, but
                // only if drag/drop.

                string targetPropertyNameErrorMessage = ValidateAssociationIdentifier(element, element.Source, (string)e.NewValue);
                if (EFModelDiagram.IsDropping && targetPropertyNameErrorMessage != null)
                {
                    element.Delete();
                }
                else
                {
                    errorMessages.Add(targetPropertyNameErrorMessage);
                }
                break;

            case "TargetRole":
                if (element.Target.IsDependentType)
                {
                    element.SourceRole = EndpointRole.Principal;
                    element.TargetRole = EndpointRole.Dependent;
                }
                else
                {
                    EndpointRole targetRole = (EndpointRole)e.NewValue;

                    if (targetRole == EndpointRole.Dependent && element.SourceRole != EndpointRole.Principal)
                    {
                        element.SourceRole = EndpointRole.Principal;
                    }
                    else if (targetRole == EndpointRole.Principal && element.SourceRole != EndpointRole.Dependent)
                    {
                        element.SourceRole = EndpointRole.Dependent;
                    }
                    SetEndpointRoles(element);
                }

                break;
            }

            errorMessages = errorMessages.Where(m => m != null).ToList();
            if (errorMessages.Any())
            {
                current.Rollback();
                ErrorDisplay.Show(string.Join("\n", errorMessages));
            }
        }