예제 #1
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 || ModelRoot.BatchUpdating)
            {
                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.GetAll <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.GetAll <UnidirectionalAssociation>()
                        .Any(a => a.Source == element))
                    {
                        errorMessages.Add($"Can't make {element.Name} a dependent class since it references other classes");

                        break;
                    }

                    if (store.GetAll <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.GetAll <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.GetAll <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(store, string.Join("\n", errorMessages));
            }
        }
예제 #2
0
        public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e)
        {
            base.ElementPropertyChanged(e);

            ModelRoot   element = (ModelRoot)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();
            bool          redraw        = false;

            switch (e.DomainProperty.Name)
            {
            case "ConnectionString":

                if (e.NewValue != null)
                {
                    element.ConnectionStringName = null;
                }

                break;

            case "ConnectionStringName":

                if (e.NewValue != null)
                {
                    element.ConnectionString = null;
                }

                break;

            case "DatabaseSchema":

                if (string.IsNullOrEmpty((string)e.NewValue))
                {
                    element.DatabaseSchema = "dbo";
                }

                break;

            case "EntityFrameworkVersion":
                element.EntityFrameworkPackageVersion = "Latest";

                if (element.EntityFrameworkVersion == EFVersion.EFCore)
                {
                    element.InheritanceStrategy = CodeStrategy.TablePerHierarchy;
                }

                break;

            case "EnumOutputDirectory":

                if (string.IsNullOrEmpty((string)e.NewValue) && !string.IsNullOrEmpty(element.EntityOutputDirectory))
                {
                    element.EnumOutputDirectory = element.EntityOutputDirectory;
                }

                break;

            case "StructOutputDirectory":

                if (string.IsNullOrEmpty((string)e.NewValue) && !string.IsNullOrEmpty(element.EntityOutputDirectory))
                {
                    element.StructOutputDirectory = element.EntityOutputDirectory;
                }

                break;

            case "EntityOutputDirectory":

                if (string.IsNullOrEmpty(element.EnumOutputDirectory) || element.EnumOutputDirectory == (string)e.OldValue)
                {
                    element.EnumOutputDirectory = (string)e.NewValue;
                }

                if (string.IsNullOrEmpty(element.StructOutputDirectory) || element.StructOutputDirectory == (string)e.OldValue)
                {
                    element.StructOutputDirectory = (string)e.NewValue;
                }

                break;

            case "FileNameMarker":
                string newFileNameMarker = (string)e.NewValue;

                if (!Regex.Match($"a.{newFileNameMarker}.cs",
                                 @"^(?!^(PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d|\..*)(\..+)?$)[^\x00-\x1f\\?*:\"";|/]+$")
                    .Success)
                {
                    errorMessages.Add("Invalid value to make part of file name");
                }

                break;

            case "InheritanceStrategy":

                if ((element.EntityFrameworkVersion == EFVersion.EFCore) && (element.NuGetPackageVersion.MajorMinorVersionNum < 2.1))
                {
                    element.InheritanceStrategy = CodeStrategy.TablePerHierarchy;
                }

                break;

            case "LayoutAlgorithm":
                ModelDisplay.LayoutDiagram(element.Classes.FirstOrDefault()?.GetActiveDiagram() as EFModelDiagram);

                break;

            case "Namespace":
                errorMessages.Add(CommonRules.ValidateNamespace((string)e.NewValue, CodeGenerator.IsValidLanguageIndependentIdentifier));

                break;

            case "ShowCascadeDeletes":

                // need these change rules to fire even though nothing in Association has changed
                // so we need to set this early -- requires guarding against recursion.
                bool newShowCascadeDeletes = (bool)e.NewValue;

                if (element.ShowCascadeDeletes != newShowCascadeDeletes)
                {
                    element.ShowCascadeDeletes = newShowCascadeDeletes;

                    foreach (Association association in store.ElementDirectory.FindElements <Association>())
                    {
                        AssociationChangeRules.UpdateDisplayForCascadeDelete(association);
                    }
                }

                redraw = true;

                break;

            case "ShowWarningsInDesigner":
                redraw = true;

                break;

            case "WarnOnMissingDocumentation":

                if (element.ShowWarningsInDesigner)
                {
                    redraw = true;
                }

                ModelRoot.ExecuteValidator?.Invoke();

                break;
            }

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

            if (errorMessages.Any())
            {
                current.Rollback();
                ErrorDisplay.Show(string.Join("\n", errorMessages));
            }

            if (redraw)
            {
                element.InvalidateDiagrams();
            }
        }
        public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e)
        {
            base.ElementPropertyChanged(e);

            ModelEnum element = (ModelEnum)e.ModelElement;

            if (element.IsDeleted)
            {
                return;
            }

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

            if (currentTransaction.IsSerializing)
            {
                return;
            }

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

            string errorMessage = null;

            switch (e.DomainProperty.Name)
            {
            case "Name":

                if (currentTransaction.Name.ToLowerInvariant() == "paste")
                {
                    return;
                }

                if (string.IsNullOrWhiteSpace(element.Name) || !CodeGenerator.IsValidLanguageIndependentIdentifier(element.Name))
                {
                    errorMessage = "Name must be a valid .NET identifier";
                }
                else if (store.GetAll <ModelClass>().Any(x => x.FullName == element.FullName))
                {
                    errorMessage = "Enum name already in use by a class";
                }
                else if (store.GetAll <ModelEnum>().Except(new[] { element }).Any(x => x.FullName == element.FullName))
                {
                    errorMessage = "Enum name already in use by another enum";
                }
                else
                {
                    // rename type names for ModelAttributes that reference this enum
                    foreach (ModelAttribute modelAttribute in store.GetAll <ModelAttribute>().Where(a => a.Type == (string)e.OldValue))
                    {
                        modelAttribute.Type = element.Name;

                        if (!string.IsNullOrEmpty(modelAttribute.InitialValue))
                        {
                            string[] parts = modelAttribute.InitialValue.Split('.');
                            parts[0] = (string)e.NewValue;
                            modelAttribute.InitialValue = string.Join(".", parts);
                        }
                    }
                }

                break;

            case "Namespace":

                if (currentTransaction.Name.ToLowerInvariant() != "paste")
                {
                    errorMessage = CommonRules.ValidateNamespace(element.Namespace, CodeGenerator.IsValidLanguageIndependentIdentifier);
                }

                break;

            case "IsFlags":

                element.SetFlagValues();

                break;

            case "ValueType":

                EnumValueType         newValueType    = (EnumValueType)e.NewValue;
                List <ModelAttribute> modelAttributes = store.ElementDirectory
                                                        .AllElements
                                                        .OfType <ModelAttribute>()
                                                        .Where(a => a.Type == element.Name && a.IsIdentity)
                                                        .ToList();

                if (modelAttributes.Any())
                {
                    string classList = string.Join(", ", modelAttributes.Select(a => a.ModelClass.Name + "." + a.Name));
                    errorMessage = $"Can't change {element.Name} value type to {newValueType}. It's not a valid identity type, and {element.Name} is used as an identity type in {classList}";
                }

                break;
            }

            if (errorMessage != null)
            {
                currentTransaction.Rollback();
                ErrorDisplay.Show(store, errorMessage);
            }
        }
예제 #4
0
        public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e)
        {
            base.ElementPropertyChanged(e);

            ModelClass element   = (ModelClass)e.ModelElement;
            ModelRoot  modelRoot = element.ModelRoot;

            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 = new List <string>();

            switch (e.DomainProperty.Name)
            {
            case "BaseClass":
            {
                if (element.IsDependentType)
                {
                    errorMessages.Add($"Can't give {element.Name} a base class since it's a dependent type");
                }

                break;
            }

            case "CustomInterfaces":
            {
                if (modelRoot.ShowInterfaceIndicators)
                {
                    PresentationHelper.UpdateClassDisplay(element);
                }

                break;
            }

            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 = MakeDefaultTableAndSetName(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.GetAll <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 "IsDatabaseView":
            {
                bool newIsView = (bool)e.NewValue;

                if (newIsView)
                {
                    if (element.IsDependentType)
                    {
                        errorMessages.Add($"Can't base {element.Name} off a view since it's a dependent type");

                        break;
                    }

                    if (element.IsQueryType)
                    {
                        errorMessages.Add($"Can't base {element.Name} off a view since it's a query type");

                        break;
                    }

                    if (string.IsNullOrEmpty(element.ViewName))
                    {
                        element.ViewName = element.TableName;
                    }

                    if (string.IsNullOrEmpty(element.ViewName))
                    {
                        element.ViewName = MakeDefaultTableAndSetName(element.Name);
                    }

                    if (modelRoot.IsEFCore5Plus)
                    {
                        VerifyKeylessTypeEFCore5();
                    }
                    else
                    {
                        VerifyKeylessType();
                    }
                }
                break;
            }

            case "IsDependentType":
            {
                if (element.IsDependentType)
                {
                    if (element.IsDatabaseView)
                    {
                        errorMessages.Add($"Can't make {element.Name} a dependent class since it's backed by a database view");

                        break;
                    }

                    if (element.IsQueryType)
                    {
                        errorMessages.Add($"Can't make {element.Name} a dependent class since it's a query type");

                        break;
                    }

                    if (element.BaseClass != null)
                    {
                        errorMessages.Add($"Can't make {element.Name} a dependent class since it has a base class");

                        break;
                    }

                    string subclasses = string.Join(", ", store.GetAll <Generalization>().Where(g => g.Superclass == element).Select(g => g.Subclass.Name));
                    if (!string.IsNullOrEmpty(subclasses))
                    {
                        errorMessages.Add($"Can't make {element.Name} a dependent class since it has subclass(es) {subclasses}");

                        break;
                    }

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

                        break;
                    }

                    List <Association> principalAssociations = store.GetAll <Association>().Where(a => a.Principal == element).ToList();

                    if (principalAssociations.Any())
                    {
                        string badAssociations = string.Join(", ", principalAssociations.Select(a => a.GetDisplayText()));
                        errorMessages.Add($"Can't make {element.Name} a dependent class since it's the principal end in: {badAssociations}");

                        break;
                    }

                    List <UnidirectionalAssociation> entityTargets = store.GetAll <UnidirectionalAssociation>().Where(a => a.Source == element && !a.Target.IsDependentType).ToList();

                    if (entityTargets.Any())
                    {
                        string badAssociations = string.Join(", ", entityTargets.Select(a => a.GetDisplayText()));
                        errorMessages.Add($"Can't make {element.Name} a dependent class since it has unidirectional associations to entities in: {badAssociations}");

                        break;
                    }

                    List <BidirectionalAssociation> bidirectionalAssociations = store.GetAll <BidirectionalAssociation>().Where(a => a.Source == element || a.Target == element).ToList();
                    if (bidirectionalAssociations.Any())
                    {
                        if (!modelRoot.IsEFCore5Plus)
                        {
                            string badAssociations = string.Join(", ", entityTargets.Select(a => a.GetDisplayText()));
                            errorMessages.Add($"Can't make {element.Name} a dependent class since it has bidirectional associations in: {badAssociations}");

                            break;
                        }

                        bidirectionalAssociations = bidirectionalAssociations.Where(a => (a.Source == element && a.TargetMultiplicity != Multiplicity.One) ||
                                                                                    (a.Target == element && a.SourceMultiplicity != Multiplicity.One))
                                                    .ToList();

                        if (bidirectionalAssociations.Any())
                        {
                            string badAssociations = string.Join(", ", entityTargets.Select(a => a.GetDisplayText()));
                            errorMessages.Add($"Can't make {element.Name} a dependent class since it has bidirectional associations without 1 or 0/1 ownership multiplicity in: {badAssociations}. The other end must be a single, required reference.");

                            break;
                        }
                    }

                    if (element.ModelRoot.EntityFrameworkVersion == EFVersion.EF6 || element.ModelRoot.GetEntityFrameworkPackageVersionNum() < 2.2)
                    {
                        if (store.GetAll <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 (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;
                    }

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

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

                // Remove any foreign keys in any incoming or outgoing associations
                foreach (Association association in Association.GetLinksToTargets(element).Union(Association.GetLinksToSources(element)).Distinct())
                {
                    association.FKPropertyName = null;
                }

                PresentationHelper.UpdateClassDisplay(element);

                break;
            }

            case "IsPropertyBag":
            {
                if (element.Superclass != null && !element.Superclass.IsPropertyBag)
                {
                    element.Superclass.IsPropertyBag = true;
                }

                if (element.Subclasses.Any())
                {
                    foreach (ModelClass subclass in element.Subclasses)
                    {
                        subclass.IsPropertyBag = true;
                    }
                }

                PresentationHelper.UpdateClassDisplay(element);
                break;
            }

            case "IsQueryType":
            {
                if ((bool)e.NewValue)
                {
                    if (element.IsDependentType)
                    {
                        errorMessages.Add($"Can't make {element.Name} a query type since it's a dependent class");
                        break;
                    }

                    if (modelRoot.EntityFrameworkVersion == EFVersion.EF6)
                    {
                        element.IsQueryType = false;
                    }
                    else if (modelRoot.IsEFCore5Plus)
                    {
                        VerifyKeylessTypeEFCore5();
                    }
                    else
                    {
                        VerifyKeylessType();
                    }
                }

                break;
            }

            case "Name":
            {
                if (current.Name.ToLowerInvariant() == "paste")
                {
                    return;
                }

                if (string.IsNullOrWhiteSpace(element.Name) || !CodeGenerator.IsValidLanguageIndependentIdentifier(element.Name))
                {
                    errorMessages.Add("Name must be a valid .NET identifier");
                }
                else if (store.GetAll <ModelClass>().Except(new[] { element }).Any(x => x.FullName == element.FullName))
                {
                    errorMessages.Add($"Class name '{element.FullName}' already in use by another class");
                }
                else if (store.GetAll <ModelEnum>().Any(x => x.FullName == element.FullName))
                {
                    errorMessages.Add($"Class name '{element.FullName}' already in use by an enum");
                }
                else if (!string.IsNullOrEmpty((string)e.OldValue))
                {
                    string oldDefaultName = MakeDefaultTableAndSetName((string)e.OldValue);
                    string newDefaultName = MakeDefaultTableAndSetName(element.Name);

                    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":
            {
                if (!element.IsDatabaseView)
                {
                    string newTableName = (string)e.NewValue;

                    if (element.IsDependentType)
                    {
                        if (!modelRoot.IsEFCore5Plus && !string.IsNullOrEmpty(newTableName))
                        {
                            element.TableName = string.Empty;
                        }
                    }
                    else
                    {
                        if (string.IsNullOrEmpty(newTableName))
                        {
                            element.TableName = MakeDefaultTableAndSetName(element.Name);
                        }

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

                break;
            }

            case "ViewName":
            {
                if (element.IsDatabaseView)
                {
                    string newViewName = (string)e.NewValue;

                    if (element.IsDependentType)
                    {
                        if (!modelRoot.IsEFCore5Plus && !string.IsNullOrEmpty(newViewName))
                        {
                            element.TableName = string.Empty;
                        }
                    }
                    else
                    {
                        if (string.IsNullOrEmpty(newViewName))
                        {
                            element.TableName = MakeDefaultTableAndSetName(element.Name);
                        }

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

                break;
            }
            }

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

            if (errorMessages.Any())
            {
                current.Rollback();
                ErrorDisplay.Show(store, string.Join("\n", errorMessages));
            }

            void VerifyKeylessTypeEFCore5()
            {
                // TODO: Find definitive documentation on query type restrictions in EFCore5+
                // Restrictions:
                // =================================
                // Cannot have a key defined.
                List <string> allIdentityAttributeNames = element.AllIdentityAttributeNames.ToList();

                if (allIdentityAttributeNames.Any())
                {
                    errorMessages.Add($"{element.Name} can't be mapped to a Sql query since it has identity attribute(s) {string.Join(", ", allIdentityAttributeNames)}. Set their 'Is Identity' property to false first.");
                }

                // Only support a subset of navigation mapping capabilities, specifically:
                //    - They may never act as the principal end of a relationship.
                string badAssociations = string.Join(", "
                                                     , store.ElementDirectory.AllElements
                                                     .OfType <Association>()
                                                     .Where(a => a.Principal == element)
                                                     .Select(a => a.GetDisplayText()));

                if (!string.IsNullOrEmpty(badAssociations))
                {
                    errorMessages.Add($"{element.Name} can't be mapped to a Sql query since it is the principal end of association(s) {badAssociations}.");
                }

                //    - They may not have navigations to owned entities
                badAssociations = string.Join(", "
                                              , store.ElementDirectory.AllElements
                                              .OfType <Association>()
                                              .Where(a => (a is UnidirectionalAssociation && a.Source == element && a.Target.IsDependentType) || (a is BidirectionalAssociation b && b.Source == element && b.Target.IsDependentType) || (a is BidirectionalAssociation c && c.Target == element && c.Source.IsDependentType))
                                              .Select(a => a.GetDisplayText()));

                if (!string.IsNullOrEmpty(badAssociations))
                {
                    errorMessages.Add($"{element.Name} can't be mapped to a Sql query since it has association(s) to dependent type(s) in {badAssociations}.");
                }

                //    - Entities cannot contain navigation properties to query types.
                badAssociations = string.Join(", "
                                              , store.ElementDirectory.AllElements
                                              .OfType <Association>()
                                              .Where(a => (a is UnidirectionalAssociation && a.Source == element && a.Target.IsQueryType) || (a is BidirectionalAssociation b && b.Source == element && b.Target.IsQueryType) || (a is BidirectionalAssociation c && c.Target == element && c.Source.IsQueryType))
                                              .Select(a => a.GetDisplayText()));

                if (!string.IsNullOrEmpty(badAssociations))
                {
                    errorMessages.Add($"{element.Name} can't be mapped to a Sql query since it has association to sql-mapped type(s) in {badAssociations}.");
                }

                //    - They can only contain reference navigation properties pointing to regular entities.
                badAssociations = string.Join(", "
                                              , store.ElementDirectory.AllElements
                                              .OfType <Association>()
                                              .Where(a => (a is UnidirectionalAssociation && a.Source == element && a.TargetMultiplicity == Multiplicity.ZeroMany) || (a is BidirectionalAssociation b && b.Source == element && b.TargetMultiplicity == Multiplicity.ZeroMany) || (a is BidirectionalAssociation c && c.Target == element && c.SourceMultiplicity == Multiplicity.ZeroMany))
                                              .Select(a => a.GetDisplayText()));

                if (!string.IsNullOrEmpty(badAssociations))
                {
                    errorMessages.Add($"{element.Name} can't be mapped to a Sql query since it has zero-to-many association(s) in {badAssociations}. Only to-one or to-zero-or-one associations are allowed. ");
                }
            }

            void VerifyKeylessType()
            {
                // Restrictions:
                // =================================
                // Cannot have a key defined.
                List <string> allIdentityAttributeNames = element.AllIdentityAttributeNames.ToList();

                if (allIdentityAttributeNames.Any())
                {
                    errorMessages.Add($"{element.Name} can't be mapped to a Sql query since it has identity attribute(s) {string.Join(", ", allIdentityAttributeNames)}. Set their 'Is Identity' property to false first.");
                }

                // Only support a subset of navigation mapping capabilities, specifically:
                //    - They may never act as the principal end of a relationship.
                string badAssociations = string.Join(", "
                                                     , store.ElementDirectory.AllElements
                                                     .OfType <Association>()
                                                     .Where(a => a.Principal == element)
                                                     .Select(a => a.GetDisplayText()));

                if (!string.IsNullOrEmpty(badAssociations))
                {
                    errorMessages.Add($"{element.Name} can't be mapped to a Sql query since it is the principal end of association(s) {badAssociations}.");
                }

                //    - They may not have navigations to owned entities
                badAssociations = string.Join(", "
                                              , store.ElementDirectory.AllElements
                                              .OfType <Association>()
                                              .Where(a => (a is UnidirectionalAssociation && a.Source == element && a.Target.IsDependentType) || (a is BidirectionalAssociation b && b.Source == element && b.Target.IsDependentType) || (a is BidirectionalAssociation c && c.Target == element && c.Source.IsDependentType))
                                              .Select(a => a.GetDisplayText()));

                if (!string.IsNullOrEmpty(badAssociations))
                {
                    errorMessages.Add($"{element.Name} can't be mapped to a Sql query since it has association(s) to dependent type(s) in {badAssociations}.");
                }

                //    - Entities cannot contain navigation properties to query types.
                badAssociations = string.Join(", "
                                              , store.ElementDirectory.AllElements
                                              .OfType <Association>()
                                              .Where(a => (a is UnidirectionalAssociation && a.Source == element && a.Target.IsQueryType) || (a is BidirectionalAssociation b && b.Source == element && b.Target.IsQueryType) || (a is BidirectionalAssociation c && c.Target == element && c.Source.IsQueryType))
                                              .Select(a => a.GetDisplayText()));

                if (!string.IsNullOrEmpty(badAssociations))
                {
                    errorMessages.Add($"{element.Name} can't be mapped to a Sql query since it has association to sql-mapped type(s) in {badAssociations}.");
                }

                //    - They can only contain reference navigation properties pointing to regular entities.
                badAssociations = string.Join(", "
                                              , store.ElementDirectory.AllElements
                                              .OfType <Association>()
                                              .Where(a => (a is UnidirectionalAssociation && a.Source == element && a.TargetMultiplicity == Multiplicity.ZeroMany) || (a is BidirectionalAssociation b && b.Source == element && b.TargetMultiplicity == Multiplicity.ZeroMany) || (a is BidirectionalAssociation c && c.Target == element && c.SourceMultiplicity == Multiplicity.ZeroMany))
                                              .Select(a => a.GetDisplayText()));

                if (!string.IsNullOrEmpty(badAssociations))
                {
                    errorMessages.Add($"{element.Name} can't be mapped to a Sql query since it has zero-to-many association(s) in {badAssociations}. Only to-one or to-zero-or-one associations are allowed. ");
                }
            }
        }
예제 #5
0
        public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e)
        {
            base.ElementPropertyChanged(e);

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

            if (current.IsSerializing)
            {
                return;
            }

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

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

                foreach (ClassShape classShape in PresentationViewsSubject.GetPresentation(element).OfType <ClassShape>())
                {
                    if (newIsAbstract)
                    {
                        classShape.OutlineColor     = Color.OrangeRed;
                        classShape.OutlineThickness = 0.02f;
                        classShape.OutlineDashStyle = element.ImplementNotify ? DashStyle.Dot : DashStyle.Dash;
                    }
                    else if (element.ImplementNotify)
                    {
                        classShape.OutlineColor     = Color.CornflowerBlue;
                        classShape.OutlineThickness = 0.02f;
                        classShape.OutlineDashStyle = DashStyle.Dot;
                    }
                    else
                    {
                        classShape.OutlineColor     = Color.Black;
                        classShape.OutlineThickness = 0.01f;
                        classShape.OutlineDashStyle = DashStyle.Solid;
                    }
                }

                break;

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

                if (!element.IsAbstract) // IsAbstract takes precedence
                {
                    foreach (ClassShape classShape in PresentationViewsSubject.GetPresentation(element).OfType <ClassShape>())
                    {
                        if (newImplementNotify)
                        {
                            classShape.OutlineColor     = Color.CornflowerBlue;
                            classShape.OutlineThickness = 0.02f;
                            classShape.OutlineDashStyle = DashStyle.Dot;
                        }
                        else
                        {
                            classShape.OutlineColor     = Color.Black;
                            classShape.OutlineThickness = 0.01f;
                            classShape.OutlineDashStyle = DashStyle.Solid;
                        }
                    }
                }

                break;

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

                if (string.IsNullOrEmpty(newTableName))
                {
                    element.TableName = MakeDefaultName(element.Name);
                }

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

            case "DbSetName":
                string newDbSetName = (string)e.NewValue;

                if (string.IsNullOrEmpty(newDbSetName))
                {
                    element.DbSetName = MakeDefaultName(element.Name);
                }

                if (current.Name.ToLowerInvariant() != "paste" &&
                    (string.IsNullOrWhiteSpace(newDbSetName) || !CodeGenerator.IsValidLanguageIndependentIdentifier(newDbSetName)))
                {
                    errorMessages.Add("DbSet name must be a valid .NET identifier");
                }

                else if (store.ElementDirectory
                         .AllElements
                         .OfType <ModelClass>()
                         .Except(new[] { element })
                         .Any(x => x.DbSetName == newDbSetName))
                {
                    errorMessages.Add($"DbSet name '{newDbSetName}' already in use");
                }

                break;

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

                if (current.Name.ToLowerInvariant() != "paste" &&
                    (string.IsNullOrWhiteSpace(newName) || !CodeGenerator.IsValidLanguageIndependentIdentifier(newName)))
                {
                    errorMessages.Add("Name must be 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;
            }

            errorMessages = errorMessages.Where(m => m != null).ToList();
            if (errorMessages.Any())
            {
                current.Rollback();
                MessageBox.Show(string.Join("; ", errorMessages));
            }
        }
예제 #6
0
        public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e)
        {
            base.ElementPropertyChanged(e);

            ModelEnum   element            = (ModelEnum)e.ModelElement;
            Store       store              = element.Store;
            Transaction currentTransaction = store.TransactionManager.CurrentTransaction;

            if (currentTransaction.IsSerializing)
            {
                return;
            }

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

            string errorMessage = null;

            switch (e.DomainProperty.Name)
            {
            case "Name":

                if (currentTransaction.Name.ToLowerInvariant() == "paste")
                {
                    return;
                }

                if (string.IsNullOrWhiteSpace(element.Name) || !CodeGenerator.IsValidLanguageIndependentIdentifier(element.Name))
                {
                    errorMessage = "Name must be a valid .NET identifier";
                }
                else if (store.ElementDirectory
                         .AllElements
                         .OfType <ModelClass>()
                         .Any(x => x.Name == element.Name))
                {
                    errorMessage = "Enum name already in use by a class";
                }
                else if (store.ElementDirectory
                         .AllElements
                         .OfType <ModelEnum>()
                         .Except(new[] { element })
                         .Any(x => x.Name == element.Name))
                {
                    errorMessage = "Enum name already in use by another enum";
                }
                else
                {
                    // rename type names for ModelAttributes that reference this enum
                    foreach (ModelAttribute modelAttribute in store.ElementDirectory.AllElements.OfType <ModelAttribute>().Where(a => a.Type == (string)e.OldValue))
                    {
                        modelAttribute.Type = element.Name;
                    }
                }

                break;

            case "Namespace":

                if (string.IsNullOrWhiteSpace(element.Namespace))
                {
                    element.Namespace = element.ModelRoot.Namespace;
                }

                if (currentTransaction.Name.ToLowerInvariant() != "paste")
                {
                    errorMessage = CommonRules.ValidateNamespace(element.Namespace, CodeGenerator.IsValidLanguageIndependentIdentifier);
                }

                break;

            case "IsFlags":
                element.SetFlagValues();

                break;
            }

            if (errorMessage != null)
            {
                currentTransaction.Rollback();
                ErrorDisplay.Show(errorMessage);
            }
        }
        public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e)
        {
            base.ElementPropertyChanged(e);

            ModelClass  element = (ModelClass)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 "IsDependentType":
                bool newIsStruct = (bool)e.NewValue;

                if (newIsStruct)
                {
                    List <Association> associations = store.ElementDirectory
                                                      .AllElements
                                                      .OfType <Association>()
                                                      .Where(a => (a.Source == element && a.SourceMultiplicity == Multiplicity.ZeroMany) ||
                                                             (a.Target == element && a.TargetMultiplicity == Multiplicity.ZeroMany))
                                                      .ToList();

                    if (associations.Any())
                    {
                        List <string> classNameList = associations.Select(a => a.Target.Name).ToList();
                        if (classNameList.Count > 1)
                        {
                            classNameList[classNameList.Count - 1] = "and " + classNameList[classNameList.Count - 1];
                        }
                        string classNames = string.Join(", ", classNameList);

                        errorMessages.Add($"Can't have a 0..* association to a dependent type. Found 0..* link(s) with {classNames}");

                        break;
                    }

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

                break;

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

                foreach (ClassShape classShape in PresentationViewsSubject.GetPresentation(element).OfType <ClassShape>())
                {
                    if (newIsAbstract)
                    {
                        classShape.OutlineColor     = Color.OrangeRed;
                        classShape.OutlineThickness = 0.02f;
                        classShape.OutlineDashStyle = element.ImplementNotify ? DashStyle.Dot : DashStyle.Dash;
                    }
                    else if (element.ImplementNotify)
                    {
                        classShape.OutlineColor     = Color.CornflowerBlue;
                        classShape.OutlineThickness = 0.02f;
                        classShape.OutlineDashStyle = DashStyle.Dot;
                    }
                    else
                    {
                        classShape.OutlineColor     = Color.Black;
                        classShape.OutlineThickness = 0.01f;
                        classShape.OutlineDashStyle = DashStyle.Solid;
                    }
                }

                break;

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

                if (!element.IsAbstract) // IsAbstract takes precedence
                {
                    foreach (ClassShape classShape in PresentationViewsSubject.GetPresentation(element).OfType <ClassShape>())
                    {
                        if (newImplementNotify)
                        {
                            classShape.OutlineColor     = Color.CornflowerBlue;
                            classShape.OutlineThickness = 0.02f;
                            classShape.OutlineDashStyle = DashStyle.Dot;
                        }
                        else
                        {
                            classShape.OutlineColor     = Color.Black;
                            classShape.OutlineThickness = 0.01f;
                            classShape.OutlineDashStyle = DashStyle.Solid;
                        }
                    }
                }

                if (element.ImplementNotify)
                {
                    foreach (ModelAttribute modelAttribute in element.Attributes.Where(x => x.AutoProperty))
                    {
                        WarningDisplay.Show($"{modelAttribute.Name} is an autoproperty, so will not participate in INotifyPropertyChanged messages");
                    }
                }

                break;

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

                if (string.IsNullOrEmpty(newTableName))
                {
                    element.TableName = MakeDefaultName(element.Name);
                }

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

            case "DbSetName":
                string newDbSetName = (string)e.NewValue;

                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.ElementDirectory
                         .AllElements
                         .OfType <ModelClass>()
                         .Except(new[] { element })
                         .Any(x => x.DbSetName == newDbSetName))
                {
                    errorMessages.Add($"DbSet name '{newDbSetName}' already in use");
                }

                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;
            }

            errorMessages = errorMessages.Where(m => m != null).ToList();
            if (errorMessages.Any())
            {
                current.Rollback();
                ErrorDisplay.Show(string.Join("; ", errorMessages));
            }
        }
예제 #8
0
        public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e)
        {
            base.ElementPropertyChanged(e);

            ModelRoot   element = (ModelRoot)e.ModelElement;
            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();
            bool          redraw        = false;

            switch (e.DomainProperty.Name)
            {
            case "ConnectionString":

                if (e.NewValue != null)
                {
                    element.ConnectionStringName = null;
                }

                break;

            case "ConnectionStringName":

                if (e.NewValue != null)
                {
                    element.ConnectionString = null;
                }

                break;

            case "EntityFrameworkVersion":
                element.EntityFrameworkPackageVersion = "Latest";

                if (element.EntityFrameworkVersion == EFVersion.EFCore)
                {
                    element.InheritanceStrategy = CodeStrategy.TablePerHierarchy;
                }

                if (element.EntityFrameworkVersion == EFVersion.EF6)
                {
                    List <Association> associations = store.ElementDirectory
                                                      .AllElements
                                                      .OfType <Association>()
                                                      .Where(a => !string.IsNullOrEmpty(a.FKPropertyName) && a.SourceMultiplicity != Multiplicity.ZeroMany && a.TargetMultiplicity != Multiplicity.ZeroMany)
                                                      .ToList();

                    string message = $"This will remove declared foreign key properties from {associations.Count} association{(associations.Count == 1 ? "" : "s")}. Are you sure?";

                    if (associations.Any() && BooleanQuestionDisplay.Show(store, message) == true)
                    {
                        foreach (Association association in associations)
                        {
                            association.FKPropertyName = null;
                            AssociationChangedRules.FixupForeignKeys(association);
                        }
                    }
                }

                ModelRoot.ExecuteValidator?.Invoke();

                break;

            case "EntityOutputDirectory":

                if (string.IsNullOrEmpty(element.EnumOutputDirectory) || element.EnumOutputDirectory == (string)e.OldValue)
                {
                    element.EnumOutputDirectory = (string)e.NewValue;
                }

                if (string.IsNullOrEmpty(element.StructOutputDirectory) || element.StructOutputDirectory == (string)e.OldValue)
                {
                    element.StructOutputDirectory = (string)e.NewValue;
                }

                break;

            case "EnumOutputDirectory":

                if (string.IsNullOrEmpty((string)e.NewValue) && !string.IsNullOrEmpty(element.EntityOutputDirectory))
                {
                    element.EnumOutputDirectory = element.EntityOutputDirectory;
                }

                break;

            case "ExposeForeignKeys":
                if (!element.ExposeForeignKeys)
                {
                    foreach (Association association in element.Store.GetAll <Association>()
                             .Where(a => (a.SourceRole == EndpointRole.Dependent || a.TargetRole == EndpointRole.Dependent) &&
                                    !string.IsNullOrWhiteSpace(a.FKPropertyName)))
                    {
                        association.FKPropertyName = null;
                        AssociationChangedRules.FixupForeignKeys(association);
                    }
                }

                break;

            case "FileNameMarker":
                string newFileNameMarker = (string)e.NewValue;

                if (!Regex.Match($"a.{newFileNameMarker}.cs",
                                 @"^(?!^(PRN|AUX|CLOCK\$|NUL|CON|COM\d|LPT\d|\..*)(\..+)?$)[^\x00-\x1f\\?*:\"";|/]+$")
                    .Success)
                {
                    errorMessages.Add("Invalid value to make part of file name");
                }

                break;

            case "GridColor":
                foreach (EFModelDiagram diagram in element.GetDiagrams())
                {
                    diagram.GridColor = (Color)e.NewValue;
                }

                redraw = true;

                break;

            case "InheritanceStrategy":

                if ((element.EntityFrameworkVersion == EFVersion.EFCore) && (element.NuGetPackageVersion.MajorMinorVersionNum < 2.1))
                {
                    element.InheritanceStrategy = CodeStrategy.TablePerHierarchy;
                }

                break;

            case "Namespace":
                errorMessages.Add(CommonRules.ValidateNamespace((string)e.NewValue, CodeGenerator.IsValidLanguageIndependentIdentifier));

                break;

            case "ShowCascadeDeletes":
                // Normally you'd think that we should be able to register this in a AssociateValueWith call
                // in AssociationConnector, but that doesn't appear to work. So call the update method here.
                foreach (Association association in store.ElementDirectory.FindElements <Association>())
                {
                    PresentationHelper.UpdateAssociationDisplay(association);
                }

                redraw = true;

                break;

            case "ShowGrid":
                foreach (EFModelDiagram diagram in element.GetDiagrams())
                {
                    diagram.ShowGrid = (bool)e.NewValue;
                }

                redraw = true;

                break;

            case "ShowWarningsInDesigner":
                redraw = true;

                if ((bool)e.NewValue)
                {
                    ModelRoot.ExecuteValidator?.Invoke();
                }

                break;

            case "SnapToGrid":
                foreach (EFModelDiagram diagram in element.GetDiagrams())
                {
                    diagram.SnapToGrid = (bool)e.NewValue;
                }

                redraw = true;

                break;

            case "StructOutputDirectory":

                if (string.IsNullOrEmpty((string)e.NewValue) && !string.IsNullOrEmpty(element.EntityOutputDirectory))
                {
                    element.StructOutputDirectory = element.EntityOutputDirectory;
                }

                break;

            case "WarnOnMissingDocumentation":

                if (element.ShowWarningsInDesigner)
                {
                    redraw = true;
                }

                ModelRoot.ExecuteValidator?.Invoke();

                break;
            }

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

            if (errorMessages.Any())
            {
                current.Rollback();
                ErrorDisplay.Show(store, string.Join("\n", errorMessages));
            }

            if (redraw)
            {
                foreach (EFModelDiagram diagram in element.GetDiagrams().Where(d => d.ActiveDiagramView != null))
                {
                    diagram.Invalidate(true);
                }
            }
        }
예제 #9
0
        public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e)
        {
            base.ElementPropertyChanged(e);

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

            if (current.IsSerializing)
            {
                return;
            }

            string errorMessage = null;

            switch (e.DomainProperty.Name)
            {
            case "Name":
                string newName = (string)e.NewValue;
                if (current.Name.ToLowerInvariant() == "paste")
                {
                    return;
                }

                if (current.Name.ToLowerInvariant() != "paste" && (string.IsNullOrWhiteSpace(newName) || !CodeGenerator.IsValidLanguageIndependentIdentifier(newName)))
                {
                    errorMessage = "Name must be a valid .NET identifier";
                }
                else if (store.ElementDirectory
                         .AllElements
                         .OfType <ModelClass>()
                         .Any(x => x.Name == newName))
                {
                    errorMessage = "Enum name already in use by a class";
                }
                else if (store.ElementDirectory
                         .AllElements
                         .OfType <ModelEnum>()
                         .Except(new[] { element })
                         .Any(x => x.Name == newName))
                {
                    errorMessage = "Enum name already in use by another enum";
                }

                break;

            case "Namespace":
                string newNamespace = (string)e.NewValue;
                if (current.Name.ToLowerInvariant() != "paste")
                {
                    errorMessage = CommonRules.ValidateNamespace(newNamespace, CodeGenerator.IsValidLanguageIndependentIdentifier);
                }
                break;

            case "IsFlags":
                bool isFlags = (bool)e.NewValue;
                element.SetFlagValues();

                break;
            }

            if (errorMessage != null)
            {
                current.Rollback();
                MessageBox.Show(errorMessage);
            }
        }