Skip to content
This repository has been archived by the owner on Jan 16, 2024. It is now read-only.

Commit

Permalink
Removed validations on model open/load that prevented a misconfigured…
Browse files Browse the repository at this point in the history
… model from loading
  • Loading branch information
msawczyn committed Aug 23, 2021
1 parent 2a03251 commit 6e195cf
Show file tree
Hide file tree
Showing 15 changed files with 107 additions and 91 deletions.
1 change: 1 addition & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
- Fixed missing '$' in generator template that was generating bad code for table schemas (see https://github.com/msawczyn/EFDesigner/issues/289)
- Restored auto-instantiation of dependent objects in entity constructors (see https://github.com/msawczyn/EFDesigner/issues/287)
- Added Microsoft.VisualStudio.Modeling.Components.15.0.dll to DslPackage assembly (see https://github.com/msawczyn/EFDesigner/issues/293)
- Removed validations on model open/load that prevented a misconfigured model from loading. Errors will still be shown during editing and when saving.

3.0.6
- Added ability to copy current diagram to clipboard
Expand Down
Binary file modified dist/Sawczyn.EFDesigner.EFModel.DslPackage.vsix
Binary file not shown.
79 changes: 22 additions & 57 deletions src/Dsl/CustomCode/Partials/Association.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,13 @@ public virtual string GetDisplayText()
internal string TargetBackingFieldNameDefault => string.IsNullOrEmpty(TargetPropertyName) ? string.Empty : $"_{TargetPropertyName.Substring(0, 1).ToLowerInvariant()}{TargetPropertyName.Substring(1)}";

internal string _targetBackingFieldName;
/// <summary>
/// Returns the calculated name of the backing field for the Target end of this association
/// </summary>
protected string GetTargetBackingFieldNameValue() => string.IsNullOrEmpty(_targetBackingFieldName) ? TargetBackingFieldNameDefault : _targetBackingFieldName;
/// <summary>
/// Sets an override for the name of the backing field for the Target end of this association
/// </summary>
protected void SetTargetBackingFieldNameValue(string value) => _targetBackingFieldName = value;

private string GetNameValue()
Expand Down Expand Up @@ -174,6 +180,17 @@ public void RedrawItem()

#endregion

internal IEnumerable<ModelAttribute> GetFKAutoIdentityErrors()
{
if (string.IsNullOrWhiteSpace(FKPropertyName))
return new ModelAttribute[0];

return FKPropertyName.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Select(name => Dependent.Attributes.FirstOrDefault(a => a.Name == name.Trim()))
.Where(a => a != null && a.IsIdentity && a.IdentityType == IdentityType.AutoGenerated)
.ToList();
}

internal bool AllCardinalitiesAreValid(out string errorMessage)
{
ModelRoot modelRoot = Source.ModelRoot;
Expand Down Expand Up @@ -267,7 +284,7 @@ private void SummaryDescriptionIsEmpty(ValidationContext context)
}
}

[ValidationMethod(ValidationCategories.Open | ValidationCategories.Save | ValidationCategories.Menu)]
[ValidationMethod(/*ValidationCategories.Open | */ValidationCategories.Save | ValidationCategories.Menu)]
[UsedImplicitly]
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "Called by validation")]
private void TPCEndpointsOnlyOnLeafNodes(ValidationContext context)
Expand All @@ -280,7 +297,7 @@ private void TPCEndpointsOnlyOnLeafNodes(ValidationContext context)
context.LogError($"{Source.Name} <=> {Target.Name}: Association endpoints can only be to most-derived classes in TPC inheritance strategy", "AEWrongEndpoints", this);
}

[ValidationMethod(ValidationCategories.Save | ValidationCategories.Load | ValidationCategories.Menu)]
[ValidationMethod(ValidationCategories.Save | ValidationCategories.Menu)]
[UsedImplicitly]
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "Called by validation")]
private void MustDetermineEndpointRoles(ValidationContext context)
Expand All @@ -296,7 +313,7 @@ private void MustDetermineEndpointRoles(ValidationContext context)
context.LogError($"{Source.Name} <=> {Target.Name}: Principal/dependent designations must be manually set for 1..1 and 0-1..0-1 associations.", "AEEndpointRoles", this);
}

[ValidationMethod(ValidationCategories.Save | ValidationCategories.Load | ValidationCategories.Menu)]
[ValidationMethod(ValidationCategories.Save | ValidationCategories.Menu)]
[UsedImplicitly]
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "Called by validation")]
private void FKPropertiesCannotBeStoreGeneratedIdentifiers(ValidationContext context)
Expand All @@ -310,59 +327,7 @@ private void FKPropertiesCannotBeStoreGeneratedIdentifiers(ValidationContext con
}
}

internal IEnumerable<ModelAttribute> GetFKAutoIdentityErrors()
{
if (string.IsNullOrWhiteSpace(FKPropertyName))
return new ModelAttribute[0];

return FKPropertyName.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Select(name => Dependent.Attributes.FirstOrDefault(a => a.Name == name.Trim()))
.Where(a => a != null && a.IsIdentity && a.IdentityType == IdentityType.AutoGenerated)
.ToList();
}

public virtual IEnumerable<string> CreateForeignKeys()
{
IEnumerable<string> result = null;

if (Principal != null && Dependent != null && string.IsNullOrWhiteSpace(FKPropertyName))
result = Principal.AllIdentityAttributes.Select(identity => $"{'"'}{CreateShadowPropertyName(identity)}{'"'}");

return result;
}

public string CreateShadowPropertyName(ModelAttribute identityAttribute)
{
string GetShadowPropertyName(string nameBase)
{
if (SourceRole == EndpointRole.Dependent)
return $"{nameBase}{identityAttribute.Name}";

// ReSharper disable once ConvertIfStatementToReturnStatement
if (this is BidirectionalAssociation)
return $"{nameBase}{identityAttribute.Name}";

return $"{nameBase}_{identityAttribute.Name}";
}

string GetShadowPropertyNameBase()
{
if (SourceRole == EndpointRole.Dependent)
return TargetPropertyName;

if (this is BidirectionalAssociation b)
return b.SourcePropertyName;

return $"{Source.Name}_{TargetPropertyName}";
}

string shadowNameBase = GetShadowPropertyNameBase();
string shadowPropertyName = GetShadowPropertyName(shadowNameBase);

return shadowPropertyName;
}

[ValidationMethod(ValidationCategories.Save | ValidationCategories.Load | ValidationCategories.Menu)]
[ValidationMethod(ValidationCategories.Save | ValidationCategories.Menu)]
[UsedImplicitly]
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "Called by validation")]
private void FKPropertiesInvalidWithoutDependentEnd(ValidationContext context)
Expand All @@ -378,7 +343,7 @@ private void FKPropertiesInvalidWithoutDependentEnd(ValidationContext context)
}
}

[ValidationMethod(ValidationCategories.Save | ValidationCategories.Load | ValidationCategories.Menu)]
[ValidationMethod(ValidationCategories.Save | ValidationCategories.Menu)]
[UsedImplicitly]
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "Called by validation")]
private void FKPropertiesMatchIdentityProperties(ValidationContext context)
Expand Down
7 changes: 6 additions & 1 deletion src/Dsl/CustomCode/Partials/ClassShape.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

namespace Sawczyn.EFDesigner.EFModel
{

public partial class ClassShape : IHighlightFromModelExplorer, IMouseActionTarget
{
/// <summary>
Expand Down Expand Up @@ -140,6 +139,9 @@ protected override CompartmentMapping[] GetCompartmentMappings(Type melType)
return mappings;
}

/// <summary>
/// Maps names to images for class glyphs
/// </summary>
public static ReadOnlyDictionary<string, Image> ClassImages =
new ReadOnlyDictionary<string, Image>(new Dictionary<string, Image>
{
Expand All @@ -151,6 +153,9 @@ protected override CompartmentMapping[] GetCompartmentMappings(Type melType)
, {nameof(Resources.AbstractEntityGlyphVisible), Resources.AbstractEntityGlyphVisible}
});

/// <summary>
/// Maps names to images for property glyphs
/// </summary>
public static ReadOnlyDictionary<string, Image> PropertyImages =
new ReadOnlyDictionary<string, Image>(new Dictionary<string, Image>
{
Expand Down
4 changes: 1 addition & 3 deletions src/Dsl/CustomCode/Partials/ModelAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -610,9 +610,7 @@ public void SetPropertyAccessModeValue(PropertyAccessMode value)
propertyAccessModeStorage = value;

if (!Store.InUndoRedoOrRollback && !this.IsLoading())
{
IsPropertyAccessModeTracking = (propertyAccessModeStorage == (ModelClass?.ModelRoot.PropertyAccessModeDefault ?? DefaultPropertyAccessMode));
}
}

#endregion
Expand Down Expand Up @@ -1024,7 +1022,7 @@ internal static (string ef6Version, string efCoreVersion)[] GeometryTypes = {
};


[ValidationMethod(ValidationCategories.Open | ValidationCategories.Save | ValidationCategories.Menu)]
[ValidationMethod(/*ValidationCategories.Open | */ValidationCategories.Save | ValidationCategories.Menu)]
[UsedImplicitly]
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "Called by validation")]
private void GeographyTypeDoesNotMatchEFVersion(ValidationContext context)
Expand Down
14 changes: 7 additions & 7 deletions src/Dsl/CustomCode/Partials/ModelClass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ private void ClassShouldHaveAttributes(ValidationContext context)
}
}

[ValidationMethod(ValidationCategories.Open | ValidationCategories.Menu)]
[ValidationMethod(/*ValidationCategories.Open | */ValidationCategories.Menu)]
[UsedImplicitly]
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "Called by validation")]
private void OwnedTypeCannotHaveABaseClass(ValidationContext context)
Expand All @@ -528,7 +528,7 @@ private void OwnedTypeCannotHaveABaseClass(ValidationContext context)
context.LogError($"Can't make {Name} a dependent class since it has a base class", "MCEOwnedHasBaseClass", this);
}

[ValidationMethod(ValidationCategories.Open | ValidationCategories.Menu)]
[ValidationMethod(/*ValidationCategories.Open | */ValidationCategories.Menu)]
[UsedImplicitly]
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "Called by validation")]
private void OwnedTypeCannotHaveASubclass(ValidationContext context)
Expand All @@ -538,7 +538,7 @@ private void OwnedTypeCannotHaveASubclass(ValidationContext context)
context.LogError($"Can't make {Name} a dependent class since it has subclass(es) {string.Join(", ", Subclasses.Select(s => s.Name))}", "MCEOwnedHasSubclass", this);
}

[ValidationMethod(ValidationCategories.Open | ValidationCategories.Menu)]
[ValidationMethod(/*ValidationCategories.Open | */ValidationCategories.Menu)]
[UsedImplicitly]
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "Called by validation")]
private void OwnedTypeCannotBeAbstract(ValidationContext context)
Expand All @@ -548,7 +548,7 @@ private void OwnedTypeCannotBeAbstract(ValidationContext context)
context.LogError($"Can't make {Name} a dependent class since it's abstract", "MCEOwnedIsAbstract", this);
}

[ValidationMethod(ValidationCategories.Open | ValidationCategories.Menu)]
[ValidationMethod(/*ValidationCategories.Open | */ValidationCategories.Menu)]
[UsedImplicitly]
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "Called by validation")]
private void OwnedTypeCannotBePrincipal(ValidationContext context)
Expand All @@ -564,7 +564,7 @@ private void OwnedTypeCannotBePrincipal(ValidationContext context)
}
}

[ValidationMethod(ValidationCategories.Open | ValidationCategories.Menu)]
[ValidationMethod(/*ValidationCategories.Open | */ValidationCategories.Menu)]
[UsedImplicitly]
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "Called by validation")]
private void OwnedTypeCannotBeInBidirectionalAssociation(ValidationContext context)
Expand All @@ -575,7 +575,7 @@ private void OwnedTypeCannotBeInBidirectionalAssociation(ValidationContext conte
context.LogError($"Can't make {Name} a dependent class since it's part of a bidirectional association", "MCEOwnedInBidirectional", this);
}

[ValidationMethod(ValidationCategories.Open | ValidationCategories.Save | ValidationCategories.Menu)]
[ValidationMethod(/*ValidationCategories.Open | */ValidationCategories.Save | ValidationCategories.Menu)]
[UsedImplicitly]
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "Called by validation")]
private void AttributesCannotBeNamedSameAsEnclosingClass(ValidationContext context)
Expand All @@ -586,7 +586,7 @@ private void AttributesCannotBeNamedSameAsEnclosingClass(ValidationContext conte
context.LogError($"{Name}: Properties can't be named the same as the enclosing class", "MCESameName", this);
}

[ValidationMethod(ValidationCategories.Open | ValidationCategories.Save | ValidationCategories.Menu)]
[ValidationMethod(/*ValidationCategories.Open | */ValidationCategories.Save | ValidationCategories.Menu)]
[UsedImplicitly]
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "Called by validation")]
private void PersistentClassesMustHaveIdentity(ValidationContext context)
Expand Down
24 changes: 18 additions & 6 deletions src/Dsl/CustomCode/Partials/ModelEnum.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,16 @@ public static bool IsUsed(ModelEnum modelEnum)
/// </value>
public string FullName => string.IsNullOrWhiteSpace(EffectiveNamespace) ? $"global::{Name}" : $"global::{EffectiveNamespace}.{Name}";

/// <summary>
/// Allows for homogenous access to the display name for this element.
/// </summary>
// ReSharper disable once UnusedMember.Global
public string GetDisplayText()
{
return Name;
}

#region Warning display
#region Warning display

// set as methods to avoid issues around serialization

Expand All @@ -62,7 +65,7 @@ public string GetDisplayText()
public void RedrawItem()
{
// redraw on every diagram
foreach (ShapeElement shapeElement in
foreach (ShapeElement shapeElement in
PresentationViewsSubject.GetPresentation(this).OfType<ShapeElement>().Distinct())
shapeElement.Invalidate();
}
Expand All @@ -85,6 +88,9 @@ protected string GetGlyphTypeValue()

#endregion

/// <summary>
/// The namespace for this element before overrides
/// </summary>
[Browsable(false)]
public string DefaultNamespace
{
Expand All @@ -108,6 +114,9 @@ public string EffectiveNamespace
}
}

/// <summary>
/// The output directory for this element's code before overrides
/// </summary>
[Browsable(false)]
public string DefaultOutputDirectory
{
Expand Down Expand Up @@ -190,12 +199,13 @@ internal virtual void ResetIsTrackingProperties()
// same with other tracking properties as they get added
}

[ValidationMethod(ValidationCategories.Open | ValidationCategories.Save | ValidationCategories.Menu)]
[ValidationMethod(/*ValidationCategories.Open | */ValidationCategories.Save | ValidationCategories.Menu)]
[UsedImplicitly]
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "Called by validation")]
private void EnumMustHaveValues(ValidationContext context)
{
if (ModelRoot == null) return;
if (ModelRoot == null)
return;

if (!Values.Any())
context.LogError($"{Name}: Enum has no values", "MEENoValues", this);
Expand All @@ -206,7 +216,8 @@ private void EnumMustHaveValues(ValidationContext context)
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "Called by validation")]
private void EnumValueInitializationsShouldBeAllOrNothing(ValidationContext context)
{
if (ModelRoot == null) return;
if (ModelRoot == null)
return;

if (Values.Any(x => !string.IsNullOrEmpty(x.Value)) && Values.Any(x => string.IsNullOrEmpty(x.Value)))
{
Expand All @@ -221,7 +232,8 @@ private void EnumValueInitializationsShouldBeAllOrNothing(ValidationContext cont
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "Called by validation")]
private void SummaryDescriptionIsEmpty(ValidationContext context)
{
if (ModelRoot == null) return;
if (ModelRoot == null)
return;

ModelRoot modelRoot = Store.ElementDirectory.FindElements<ModelRoot>().FirstOrDefault();
if (modelRoot?.WarnOnMissingDocumentation == true && string.IsNullOrWhiteSpace(Summary))
Expand Down
Loading

0 comments on commit 6e195cf

Please sign in to comment.