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

Commit

Permalink
Debugging dupe check in Parser Get*Associations
Browse files Browse the repository at this point in the history
  • Loading branch information
msawczyn committed Dec 23, 2019
1 parent c3f0a54 commit 013eed2
Show file tree
Hide file tree
Showing 26 changed files with 211 additions and 42 deletions.
3 changes: 2 additions & 1 deletion rebuild.cmd
@@ -1,6 +1,7 @@
cd src
VSIXInstaller.exe /q /u:"56bbe1ba-aaee-4883-848f-e3c8656f8db2"
msbuild efdesigner.sln /t:Rebuild /p:Configuration=Debug
del "..\dist\Sawczyn.EFDesigner.EFModel.DslPackage.vsix"
REM msbuild efdesigner.sln /t:Rebuild /p:Configuration=Debug
msbuild efdesigner.sln /t:Rebuild /p:Configuration=Release
copy /Y "DslPackage\bin\Release\Sawczyn.EFDesigner.EFModel.DslPackage.vsix" ..\dist
VSIXInstaller.exe /q "..\dist\Sawczyn.EFDesigner.EFModel.DslPackage.vsix"
Expand Down
12 changes: 2 additions & 10 deletions src/Dsl/CustomCode/Partials/ModelClass.cs
Expand Up @@ -81,18 +81,10 @@ public IEnumerable<string> AllPropertyNames
{
List<string> result = AllAttributes.Select(a => a.Name).ToList();

result.AddRange(Association.GetLinksToSources(this)
.Where(a => a.Target.Name == Name && a.TargetRole == EndpointRole.Dependent && !string.IsNullOrWhiteSpace(a.FKPropertyName))
.SelectMany(a => a.FKPropertyName.Split(',')));

result.AddRange(Association.GetLinksToTargets(this)
.Where(a => a.Source.Name == Name && a.SourceRole == EndpointRole.Dependent && !string.IsNullOrWhiteSpace(a.FKPropertyName))
.SelectMany(a => a.FKPropertyName.Split(',')));

result.AddRange(AllNavigationProperties().Select(np => np.PropertyName));

if (Superclass != null)
result.AddRange(Superclass.AllPropertyNames);
//if (Superclass != null)
// result.AddRange(Superclass.AllPropertyNames);

return result;
}
Expand Down
1 change: 1 addition & 0 deletions src/Dsl/CustomCode/Partials/ModelRoot.cs
Expand Up @@ -24,6 +24,7 @@ namespace Sawczyn.EFDesigner.EFModel
public partial class ModelRoot: IHasStore
{
public static readonly PluralizationService PluralizationService;
internal static bool BatchUpdating = false;

public static Action ExecuteValidator { get; set; }

Expand Down
2 changes: 1 addition & 1 deletion src/Dsl/CustomCode/Rules/AssociationAddRules.cs
Expand Up @@ -16,7 +16,7 @@ public override void ElementAdded(ElementAddedEventArgs e)
Transaction current = store.TransactionManager.CurrentTransaction;
PluralizationService pluralizationService = ModelRoot.PluralizationService;

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

// add unidirectional
Expand Down
19 changes: 15 additions & 4 deletions src/Dsl/CustomCode/Rules/AssociationChangeRules.cs
Expand Up @@ -58,7 +58,7 @@ public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e)
Store store = element.Store;
Transaction current = store.TransactionManager.CurrentTransaction;

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

if (Equals(e.NewValue, e.OldValue))
Expand Down Expand Up @@ -96,16 +96,27 @@ public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e)

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

foreach (string propertyName in fkPropertyNames)
{
if (!CodeGenerator.IsValidLanguageIndependentIdentifier(propertyName))
errorMessages.Add($"{tag} FK property name '{propertyName}' isn't a valid .NET identifier");
else if (dependentClass.AllPropertyNames.Count(a => a == propertyName) > 1)
errorMessages.Add($"{tag} FK property name '{dependentClass.Name}.{propertyName}' already in use");

// if a foreign key property is added to the association and there is already a property with that name,
// we'll assume the user was confused and thought they needed to do that (otherwise, it's an error since we're going to generate that
// property later).
// So we'll have the foreign key take precedence and remove the existing property unless that property is in a
// base class. That's too far removed, so we'll throw an error
if (dependentClass.AllAttributes.Except(dependentClass.Attributes).Any(a => a.Name == propertyName))
errorMessages.Add($"{tag} FK property name '{propertyName}' is used in a base class of {dependentClass.Name}");
else
{
foreach (ModelAttribute t in dependentClass.Attributes.Where(a => a.Name == propertyName).ToArray())
dependentClass.Attributes.Remove(t);
}
}
}
}
Expand Down
Expand Up @@ -13,7 +13,7 @@ public override void ElementAdded(ElementAddedEventArgs e)
Store store = element.Store;
Transaction current = store.TransactionManager.CurrentTransaction;

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

PresentationHelper.UpdateAssociationDisplay(element);
Expand Down
2 changes: 1 addition & 1 deletion src/Dsl/CustomCode/Rules/GeneralizationAddRules.cs
Expand Up @@ -16,7 +16,7 @@ public override void ElementAdded(ElementAddedEventArgs e)
Store store = element.Store;
Transaction current = store.TransactionManager.CurrentTransaction;

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

if (element.IsInCircularInheritance())
Expand Down
2 changes: 1 addition & 1 deletion src/Dsl/CustomCode/Rules/GeneralizationChangeRules.cs
Expand Up @@ -19,7 +19,7 @@ public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e)
Store store = element.Store;
Transaction current = store.TransactionManager.CurrentTransaction;

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

if (Equals(e.NewValue, e.OldValue))
Expand Down
2 changes: 1 addition & 1 deletion src/Dsl/CustomCode/Rules/GeneralizationDeletingRules.cs
Expand Up @@ -19,7 +19,7 @@ public override void ElementDeleting(ElementDeletingEventArgs e)
Store store = element.Store;
Transaction current = store.TransactionManager.CurrentTransaction;

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

if (element.Superclass.IsDeleting)
Expand Down
2 changes: 1 addition & 1 deletion src/Dsl/CustomCode/Rules/ModelAttributeChangeRules.cs
Expand Up @@ -27,7 +27,7 @@ public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e)
Store store = element.Store;
Transaction current = store.TransactionManager.CurrentTransaction;

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

if (Equals(e.NewValue, e.OldValue))
Expand Down
2 changes: 1 addition & 1 deletion src/Dsl/CustomCode/Rules/ModelClassAddRules.cs
Expand Up @@ -18,7 +18,7 @@ public override void ElementAdded(ElementAddedEventArgs e)
Transaction current = store.TransactionManager.CurrentTransaction;
ModelRoot modelRoot = store.ModelRoot();

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

// there could already be an identity property if this class was created via Paste or import
Expand Down
2 changes: 1 addition & 1 deletion src/Dsl/CustomCode/Rules/ModelClassChangeRules.cs
Expand Up @@ -22,7 +22,7 @@ public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e)
Store store = element.Store;
Transaction current = store.TransactionManager.CurrentTransaction;

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

if (Equals(e.NewValue, e.OldValue))
Expand Down
2 changes: 1 addition & 1 deletion src/Dsl/CustomCode/Rules/ModelClassDeletingRules.cs
Expand Up @@ -18,7 +18,7 @@ public override void ElementDeleting(ElementDeletingEventArgs e)
Store store = element.Store;
Transaction current = store.TransactionManager.CurrentTransaction;

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

List<Generalization> generalizations = store.Get<Generalization>().Where(g => g.Superclass == element).ToList();
Expand Down
2 changes: 1 addition & 1 deletion src/Dsl/CustomCode/Rules/ModelEnumValueAddRules.cs
Expand Up @@ -17,7 +17,7 @@ public override void ElementAdded(ElementAddedEventArgs e)
Store store = element.Store;
Transaction current = store.TransactionManager.CurrentTransaction;

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

enumElement.SetFlagValue(element);
Expand Down
2 changes: 1 addition & 1 deletion src/Dsl/CustomCode/Rules/ModelEnumValueChangeRules.cs
Expand Up @@ -24,7 +24,7 @@ public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e)
Store store = element.Store;
Transaction current = store.TransactionManager.CurrentTransaction;

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

if (Equals(e.NewValue, e.OldValue))
Expand Down
2 changes: 1 addition & 1 deletion src/Dsl/CustomCode/Rules/ModelRootChangeRules.cs
Expand Up @@ -20,7 +20,7 @@ public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e)
Store store = element.Store;
Transaction current = store.TransactionManager.CurrentTransaction;

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

if (Equals(e.NewValue, e.OldValue))
Expand Down
Expand Up @@ -13,7 +13,7 @@ public override void ElementAdded(ElementAddedEventArgs e)
Store store = element.Store;
Transaction current = store.TransactionManager.CurrentTransaction;

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

PresentationHelper.UpdateAssociationDisplay(element);
Expand Down
11 changes: 10 additions & 1 deletion src/Dsl/CustomCode/Utilities/Import/AssemblyProcessor.cs
Expand Up @@ -139,6 +139,7 @@ private void ProcessProperties(ModelClass modelClass, List<ModelProperty> proper

if (element == null)
{
// we've never seen this one before. Add it.
element = new ModelAttribute(Store,
new PropertyAssignment(ModelAttribute.TypeDomainPropertyId, data.TypeName),
new PropertyAssignment(ModelAttribute.NameDomainPropertyId, data.Name),
Expand All @@ -147,11 +148,15 @@ private void ProcessProperties(ModelClass modelClass, List<ModelProperty> proper
new PropertyAssignment(ModelAttribute.RequiredDomainPropertyId, data.Required),
new PropertyAssignment(ModelAttribute.MaxLengthDomainPropertyId, data.MaxStringLength),
new PropertyAssignment(ModelAttribute.MinLengthDomainPropertyId, data.MinStringLength),
new PropertyAssignment(ModelAttribute.IsIdentityDomainPropertyId, data.IsIdentity));
new PropertyAssignment(ModelAttribute.IsIdentityDomainPropertyId, data.IsIdentity),
new PropertyAssignment(ModelAttribute.IdentityTypeDomainPropertyId, data.IsIdentity
? data.IsIdentityGenerated ? IdentityType.AutoGenerated : IdentityType.Manual
: IdentityType.None));
modelClass.Attributes.Add(element);
}
else
{
// somehow, we have seen this before. Update it.
element.Type = data.TypeName;
element.Name = data.Name;
element.CustomAttributes = data.CustomAttributes;
Expand All @@ -160,6 +165,10 @@ private void ProcessProperties(ModelClass modelClass, List<ModelProperty> proper
element.MaxLength = data.MaxStringLength;
element.MinLength = data.MinStringLength;
element.IsIdentity = data.IsIdentity;

element.IdentityType = data.IsIdentity
? data.IsIdentityGenerated ? IdentityType.AutoGenerated : IdentityType.Manual
: IdentityType.None;
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/Dsl/CustomCode/Utilities/Import/FileDropHelper.cs
Expand Up @@ -100,6 +100,7 @@ private static void Process(Store store, string filename, AssemblyProcessor asse
try
{
Cursor.Current = Cursors.WaitCursor;
ModelRoot.BatchUpdating = true;

if (IsAssembly(filename))
{
Expand Down Expand Up @@ -129,6 +130,8 @@ private static void Process(Store store, string filename, AssemblyProcessor asse
finally
{
Cursor.Current = Cursors.Default;
ModelRoot.BatchUpdating = false;

StatusDisplay.Show("");
}
}
Expand Down
1 change: 0 additions & 1 deletion src/Testing/Sandbox_EF6/EFModel.cs
@@ -1 +0,0 @@

2 changes: 1 addition & 1 deletion src/Testing/Sandbox_EF6/EFModel.efmodel
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<modelRoot xmlns:dm0="http://schemas.microsoft.com/VisualStudio/2008/DslTools/Core" dslVersion="1.3.1.0" Id="cba47279-0950-4257-bb2c-e4d5e72a52a4" entityContainerName="EFModel" namespace="Sandbox" connectionString="Data Source=.;Initial Catalog=Sandbox;Integrated Security=True" automaticMigrationsEnabled="false" entityOutputDirectory="Generated\Entities" contextOutputDirectory="Generated\Context" enumOutputDirectory="Generated\Enums" inheritanceStrategy="TablePerType" transformOnSave="false" defaultIdentityType="Int64" showCascadeDeletes="true" databaseType="None" warnOnMissingDocumentation="false" structOutputDirectory="Generated\Structs" showWarningsInDesigner="false" layoutAlgorithmSettings="" entityNamespace="Sandbox" enumNamespace="Sandbox" namespaces="" outputLocations="" exposeForeignKeys="true" xmlns="http://schemas.microsoft.com/dsltools/EFModel" />
<modelRoot xmlns:dm0="http://schemas.microsoft.com/VisualStudio/2008/DslTools/Core" dslVersion="1.4.0.0" Id="cba47279-0950-4257-bb2c-e4d5e72a52a4" entityContainerName="IncludeContext" namespace="Include.Domain.Models" connectionString="Data Source=.;Initial Catalog=Sandbox;Integrated Security=True" automaticMigrationsEnabled="false" entityOutputDirectory="Generated\Entities" contextOutputDirectory="Generated\Context" enumOutputDirectory="Generated\Enums" inheritanceStrategy="TablePerType" transformOnSave="false" defaultIdentityType="Int64" showCascadeDeletes="true" databaseType="None" warnOnMissingDocumentation="false" structOutputDirectory="Generated\Structs" showWarningsInDesigner="false" layoutAlgorithm="FastIncremental" layoutAlgorithmSettings="Fast Incremental Layout Settings" entityNamespace="Sandbox" enumNamespace="Sandbox" namespaces="" outputLocations="" exposeForeignKeys="true" xmlns="http://schemas.microsoft.com/dsltools/EFModel" />
2 changes: 1 addition & 1 deletion src/Testing/Sandbox_EF6/EFModel.efmodel.diagram
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<eFModelDiagram dslVersion="1.3.1.0" Id="e64a0ebe-73bd-4499-bbd2-d6c1e8597a6f" absoluteBounds="0, 0, 11, 8.5" name="EFModel">
<eFModelDiagram dslVersion="1.4.0.0" Id="e64a0ebe-73bd-4499-bbd2-d6c1e8597a6f" absoluteBounds="0, 0, 11, 8.5" name="EFModel">
<modelRootMoniker Id="cba47279-0950-4257-bb2c-e4d5e72a52a4" />
</eFModelDiagram>
44 changes: 35 additions & 9 deletions src/Utilities/EF6ParserFmwk/Parser.cs
Expand Up @@ -70,10 +70,19 @@ public Parser(Assembly assembly, string dbContextTypeName = null)
throw new MissingMethodException("Can't find constructor with one string parameter (connection string or connection name)");
}

DbContextInfo dbContextInfo = new DbContextInfo(contextType, new DbProviderInfo("System.Data.SqlClient", "2008"));
dbContext = dbContextInfo.CreateInstance() ?? throw new Exception($"Failed to create an instance of {contextType.FullName}. Does it have a default constructor?");
try
{
DbContextInfo dbContextInfo = new DbContextInfo(contextType, new DbProviderInfo("System.Data.SqlClient", "2008"));
dbContext = dbContextInfo.CreateInstance();
}
catch (InvalidOperationException e)
{
dbContext = assembly.CreateInstance(contextType.FullName, false, BindingFlags.Default, null, new object[] { "App=EntityFramework" }, null, null) as DbContext
?? throw new Exception($"Failed to create an instance of {contextType.FullName}. "
+ "Please ensure it has either a default constructor or a constructor with one string parameter (connection string or connection name)"
, e);
}

//dbContext = assembly.CreateInstance(contextType.FullName, false, BindingFlags.Default, null, new object[] { "App=EntityFramework" }, null, null) as DbContext;
metadata = ((IObjectContextAdapter)dbContext).ObjectContext.MetadataWorkspace;
}

Expand Down Expand Up @@ -106,6 +115,9 @@ private List<ModelBidirectionalAssociation> GetBidirectionalAssociations(EntityT
{
List<ModelBidirectionalAssociation> result = new List<ModelBidirectionalAssociation>();

if (entityType == null)
return result;

foreach (NavigationProperty navigationProperty in entityType.DeclaredNavigationProperties.Where(np => Inverse(np) != null))
{
// ReSharper disable UseObjectOrCollectionInitializer
Expand Down Expand Up @@ -139,13 +151,17 @@ private List<ModelBidirectionalAssociation> GetBidirectionalAssociations(EntityT

// look for declared foreign keys
List<EdmProperty> dependentProperties = navigationProperty.GetDependentProperties().ToList();

if (dependentProperties.Any())
association.ForeignKey = string.Join(",", dependentProperties.Select(p => p.Name));

log.Info($"Found bidirectional association {association.SourceClassName}.{association.TargetPropertyName} <-> {association.TargetClassName}.{association.SourcePropertyTypeName}");
log.Info("\n " + JsonConvert.SerializeObject(association));

result.Add(association);
// duplicate check
if (result.All(a => a != association && a.Inverse() != association))
{
log.Info($"Found bidirectional association {association.SourceClassName}.{association.TargetPropertyName} <-> {association.TargetClassName}.{association.SourcePropertyTypeName}");
log.Info("\n " + JsonConvert.SerializeObject(association));
result.Add(association);
}
}

return result;
Expand Down Expand Up @@ -222,6 +238,9 @@ private List<ModelUnidirectionalAssociation> GetUnidirectionalAssociations(Entit
{
List<ModelUnidirectionalAssociation> result = new List<ModelUnidirectionalAssociation>();

if (entityType == null)
return result;

foreach (NavigationProperty navigationProperty in entityType.NavigationProperties.Where(np => Inverse(np) == null))
{
ModelUnidirectionalAssociation association = new ModelUnidirectionalAssociation();
Expand Down Expand Up @@ -250,9 +269,16 @@ private List<ModelUnidirectionalAssociation> GetUnidirectionalAssociations(Entit
if (dependentProperties.Any())
association.ForeignKey = string.Join(",", dependentProperties.Select(p => p.Name));

log.Info("\n " + JsonConvert.SerializeObject(association));
string json = JsonConvert.SerializeObject(association);

// duplicate check
if (result.All(a => a != association))
{
log.Info($"Found unidirectional association {association.SourceClassName}.{association.TargetPropertyName} -> {association.TargetClassName}");
log.Info("\n " + json);
result.Add(association);
}

result.Add(association);
}

return result;
Expand Down

0 comments on commit 013eed2

Please sign in to comment.