Skip to content

Commit

Permalink
Fix Entity Framework Child\Parent relationship generation (#179)
Browse files Browse the repository at this point in the history
* add generator attributes to foreign key gens

* output text to unit test logger

* moved foreign key logic away from the old t4 gen model

* now generating the one to many interface

* adjust type parsing to use ParseTypeName

* add foreign key property

* add the child relationship generation

* removed defunct test from cgr

no longer using attributes to drive config

* fixed key gen and sample data

* add inherited documentation

* padding out the ef model generation

* ef model now generating foreign entities

* ef logic now builds in sample app

* corrected ef model generation for relationships

* prep for entitytype config range constraints

* prep for min and max value constraints

* Update version.json

* prep of relationship mapping in entity type config

* add more event id's

* change primary key generation as now explicit

* fixed null ref when no properties in a ef table

* invocation logic for child\parent relationships

* removing static keyword from private methods

micro optimisation and going to add logging down the road
  • Loading branch information
dpvreony committed Oct 31, 2021
1 parent eed3771 commit 1acfd29
Show file tree
Hide file tree
Showing 50 changed files with 889 additions and 194 deletions.
43 changes: 29 additions & 14 deletions src/Dhgms.Nucleotide.GenerationTests/EventIdExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,34 @@
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Extensions.Logging;

namespace Dhgms.Nucleotide.GenerationTests
namespace Dhgms.Nucleotide.GenerationTests
{
public static class NumericEventIds
{
public const int UserControllerAddId = 1;
public const int UserControllerOnAddNotifySignalRId = 2;
public const int UserControllerDeleteId = 3;
public const int UserControllerOnDeleteNotifySignalRId = 4;
public const int UserControllerListId = 5;
public const int UserControllerUpdateId = 6;
public const int UserControllerOnUpdateNotifySignalRId = 7;
public const int UserControllerViewId = 8;
public const int UserControllerAddId = 1,
UserControllerOnAddNotifySignalRId = 2,
UserControllerDeleteId = 3,
UserControllerOnDeleteNotifySignalRId = 4,
UserControllerListId = 5,
UserControllerUpdateId = 6,
UserControllerOnUpdateNotifySignalRId = 7,
UserControllerViewId = 8,
AddressControllerAddId = 9,
AddressControllerDeleteId = 10,
AddressControllerListId = 11,
AddressControllerUpdateId = 12,
AddressControllerViewId = 13,
GenderControllerAddId = 14,
GenderControllerDeleteId = 15,
GenderControllerListId = 16,
GenderControllerUpdateId= 17,
GenderControllerViewId = 18,
PersonControllerAddId = 19,
PersonControllerDeleteId = 20,
PersonControllerListId = 21,
PersonControllerUpdateId = 22,
PersonControllerViewId = 23,
SalutationControllerAddId = 24,
SalutationControllerDeleteId = 25,
SalutationControllerListId = 26,
SalutationControllerUpdateId = 27,
SalutationControllerViewId= 28;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;


namespace Dhgms.Nucleotide.Generators.Features.Database
{
public sealed class ForiegnKeyInterfaceFeatureFlags
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
using Dhgms.Nucleotide.Generators.Generators;
using Dhgms.Nucleotide.Generators.Models;

namespace Dhgms.Nucleotide.Generators.Features.Database
{
public abstract class ForiegnKeyInterfaceGenerator : BaseGenerator<ForiegnKeyInterfaceFeatureFlags, ForiegnKeyInterfaceGeneratorProcessor, IEntityGenerationModel>
public abstract class ForiegnKeyInterfaceGenerator : BaseGenerator<ForiegnKeyInterfaceFeatureFlags, ForiegnKeyInterfaceGeneratorProcessor, ReferencedByEntityGenerationModel>
{
/// <inheritdoc />
protected override string GetNamespace()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
using System;
using Dhgms.Nucleotide.Generators.GeneratorProcessors;
using Dhgms.Nucleotide.Generators.Models;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace Dhgms.Nucleotide.Generators.Features.Database
{
public sealed class ForiegnKeyInterfaceGeneratorProcessor : BaseInterfaceLevelCodeGeneratorProcessor<IEntityGenerationModel>
public sealed class ForiegnKeyInterfaceGeneratorProcessor : BaseInterfaceLevelCodeGeneratorProcessor<ReferencedByEntityGenerationModel>
{
/// <inheritdoc />
protected override string[] GetClassPrefixes()
{
throw new NotImplementedException();
return null;
}

/// <inheritdoc />
Expand All @@ -20,7 +22,7 @@ protected override string GetClassSuffix()
}

/// <inheritdoc />
protected override string[] GetInterfaceSummary(IEntityGenerationModel entityDeclaration)
protected override string[] GetInterfaceSummary(ReferencedByEntityGenerationModel entityDeclaration)
{
return new[]
{
Expand All @@ -29,21 +31,52 @@ protected override string[] GetInterfaceSummary(IEntityGenerationModel entityDec
}

/// <inheritdoc />
protected override PropertyDeclarationSyntax[] GetPropertyDeclarations(IEntityGenerationModel entityGenerationModel, string prefix)
protected override PropertyDeclarationSyntax[] GetPropertyDeclarations(ReferencedByEntityGenerationModel entityGenerationModel, string prefix)
{
throw new NotImplementedException();
var accessorList = new[]
{
SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)),
SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)),
};

var pocoSummary = GetSummary(new[] { $"Gets or Sets the Foreign Entity for {entityGenerationModel.ClassName}" });

var pocoType = SyntaxFactory.ParseTypeName($"EfModels.{entityGenerationModel.EntityType}EfModel");
var pocoIdentifier = entityGenerationModel.SingularPropertyName;

var pocoObject = RoslynGenerationHelpers.GetPropertyDeclarationSyntax(pocoType, pocoIdentifier, pocoSummary);

var foreignKeySummary = GetSummary(new[] { $"Gets or Sets the Foreign Key for {entityGenerationModel.ClassName}" });
var foreignKeyType = SyntaxFactory.ParseTypeName(entityGenerationModel.KeyType);
var foreignKeyIdentifier = $"{entityGenerationModel.SingularPropertyName}Id";
var foreignKey = SyntaxFactory.PropertyDeclaration(foreignKeyType, foreignKeyIdentifier)
.AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword))
.WithAccessorList(
SyntaxFactory.AccessorList(
SyntaxFactory.List(accessorList)
))
.WithLeadingTrivia(foreignKeySummary);


return new []
{
foreignKey,
pocoObject,
};
}

/// <inheritdoc />
protected override MethodDeclarationSyntax[] GetMethodDeclarations(string className, string prefix)
{
throw new NotImplementedException();
return null;
}

/// <inheritdoc />
protected override string[] GetBaseInterfaces(IEntityGenerationModel entityGenerationModel, string prefix)
protected override string[] GetBaseInterfaces(ReferencedByEntityGenerationModel entityGenerationModel, string prefix)
{
throw new NotImplementedException();
return null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using Dhgms.Nucleotide.Generators.GeneratorProcessors;

namespace Dhgms.Nucleotide.Generators.Features.Database
{
/// <summary>
/// Generation Model for a One to Many Relationship
/// </summary>
public sealed class ReferencedByEntityGenerationModel : IClassName
{
/// <summary>
///
/// </summary>
/// <param name="namespaceForInterface">The namespace the interface will be located in.</param>
/// <param name="entityName">The name of the entity.</param>
/// <param name="entityType">The type for the entity</param>
/// <param name="propertyName">The name of the navigation property</param>
/// <param name="keyType">The type for the foreign key.</param>
public ReferencedByEntityGenerationModel(
string namespaceForInterface,
string entityName,
string entityType,
string singularPropertyName,
string pluralPropertyName,
string keyType)
{
NamespaceForInterface = namespaceForInterface;
ClassName = entityName;
EntityType = entityType;
SingularPropertyName = singularPropertyName;
PluralPropertyName = pluralPropertyName;
KeyType = keyType;
}

/// <summary>
/// Gets the namespace the interface will be located in.
/// </summary>
public string NamespaceForInterface { get; }

/// <summary>
/// Gets the name of the entity.
/// </summary>
public string ClassName { get; }

/// <summary>
/// Gets the type for the entity.
/// </summary>
public string EntityType { get; }

/// <summary>
/// Gets the singular name of the navigation property.
/// </summary>
public string SingularPropertyName { get; }

/// <summary>
/// Gets the plural name of the navigation property.
/// </summary>
public string PluralPropertyName { get; }

/// <summary>
/// Gets the type for the foreign key.
/// </summary>
public string KeyType { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Dhgms.Nucleotide.Generators.Features.Database
{
public abstract class ReferencedByEntityGenerator : BaseGenerator<ReferencedByEntityFeatureFlags, ReferencedByEntityGeneratorProcessor, IEntityGenerationModel>
public abstract class ReferencedByEntityGenerator : BaseGenerator<ReferencedByEntityFeatureFlags, ReferencedByEntityGeneratorProcessor, ReferencedByEntityGenerationModel>
{
/// <inheritdoc />
protected override string GetNamespace()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
using Dhgms.Nucleotide.Generators.GeneratorProcessors;
using Dhgms.Nucleotide.Generators.Models;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace Dhgms.Nucleotide.Generators.Features.Database
{
public sealed class ReferencedByEntityGeneratorProcessor : BaseInterfaceLevelCodeGeneratorProcessor<IEntityGenerationModel>
public sealed class ReferencedByEntityGeneratorProcessor : BaseInterfaceLevelCodeGeneratorProcessor<ReferencedByEntityGenerationModel>
{
/// <inheritdoc />
protected override string[] GetClassPrefixes()
Expand All @@ -20,30 +22,48 @@ protected override string GetClassSuffix()
}

/// <inheritdoc />
protected override string[] GetInterfaceSummary(IEntityGenerationModel entityDeclaration)
protected override string[] GetInterfaceSummary(ReferencedByEntityGenerationModel entityDeclaration)
{
return new[]
{
"Represents a entity",
$"Represents a one to many relationship for the {entityDeclaration.ClassName} entity where this is the one (principal) side.",
};
}

/// <inheritdoc />
protected override PropertyDeclarationSyntax[] GetPropertyDeclarations(IEntityGenerationModel entityGenerationModel, string prefix)
protected override PropertyDeclarationSyntax[] GetPropertyDeclarations(ReferencedByEntityGenerationModel entityGenerationModel, string prefix)
{
throw new NotImplementedException();
var accessorList = new[]
{
SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)),
SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)),
};

var pocoSummary = GetSummary(new[] { $"Gets or Sets the Foreign Entity for {entityGenerationModel.ClassName}" });

var pocoType = SyntaxFactory.ParseTypeName($"global::System.Collections.Generic.ICollection<EfModels.{entityGenerationModel.EntityType}EfModel>");
var pocoIdentifier = entityGenerationModel.PluralPropertyName;

var pocoObject = RoslynGenerationHelpers.GetPropertyDeclarationSyntax(pocoType, pocoIdentifier, pocoSummary);

return new []
{
pocoObject,
};
}

/// <inheritdoc />
protected override MethodDeclarationSyntax[] GetMethodDeclarations(string className, string prefix)
{
throw new NotImplementedException();
return null;
}

/// <inheritdoc />
protected override string[] GetBaseInterfaces(IEntityGenerationModel entityGenerationModel, string prefix)
protected override string[] GetBaseInterfaces(ReferencedByEntityGenerationModel entityGenerationModel, string prefix)
{
throw new NotImplementedException();
return null;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using Dhgms.Nucleotide.Generators.Generators;
using Dhgms.Nucleotide.Generators.Models;

namespace Dhgms.Nucleotide.Generators.Features.Dto
{
public abstract class RequestDtoClassGenerator : BaseClassLevelCodeGenerator<RequestDtoClassFeatureFlags, RequestDtoClassGeneratorProcessor>
public abstract class RequestDtoClassGenerator : BaseClassLevelCodeGenerator<RequestDtoClassFeatureFlags, RequestDtoClassGeneratorProcessor, IEntityGenerationModel>
{
protected override string GetNamespace() => "RequestDtos";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public sealed class RequestDtoClassGeneratorProcessor : BaseClassLevelCodeGenera

protected override MethodDeclarationSyntax[] GetMethodDeclarations(IEntityGenerationModel entityGenerationModel) => Array.Empty<MethodDeclarationSyntax>();

protected override PropertyDeclarationSyntax[] GetPropertyDeclarations(IEntityGenerationModel entityGenerationModel) => Array.Empty<PropertyDeclarationSyntax>();
protected override IEnumerable<PropertyDeclarationSyntax> GetPropertyDeclarations(IEntityGenerationModel entityGenerationModel) => Array.Empty<PropertyDeclarationSyntax>();

protected override string[] GetClassLevelCommentSummary(string entityName)
{
Expand All @@ -42,7 +42,7 @@ protected override string[] GetClassLevelCommentSummary(string entityName)

protected override string GetBaseClass(string entityName) => null;

protected override IList<string> GetImplementedInterfaces(string entityName) => Array.Empty<string>();
protected override IEnumerable<string> GetImplementedInterfaces(IEntityGenerationModel entityGenerationModel) => Array.Empty<string>();

protected override IList<Tuple<string, IList<string>>> GetClassAttributes(IEntityGenerationModel entityDeclaration)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using Dhgms.Nucleotide.Generators.Generators;
using Dhgms.Nucleotide.Generators.Models;

namespace Dhgms.Nucleotide.Generators.Features.Dto
{
public abstract class ResponseDtoClassGenerator : BaseClassLevelCodeGenerator<ResponseDtoClassFeatureFlags, ResponseDtoClassGeneratorProcessor>
public abstract class ResponseDtoClassGenerator : BaseClassLevelCodeGenerator<ResponseDtoClassFeatureFlags, ResponseDtoClassGeneratorProcessor, IEntityGenerationModel>
{
protected override string GetNamespace()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public sealed class ResponseDtoClassGeneratorProcessor : BaseClassLevelCodeGener

protected override IList<string> GetBaseConstructorArguments() => null;

protected override PropertyDeclarationSyntax[] GetPropertyDeclarations(IEntityGenerationModel entityGenerationModel)
protected override IEnumerable<PropertyDeclarationSyntax> GetPropertyDeclarations(IEntityGenerationModel entityGenerationModel)
{
return null;
}
Expand Down Expand Up @@ -63,7 +63,7 @@ protected override string GetBaseClass(string entityName)
return null;
}

protected override IList<string> GetImplementedInterfaces(string entityName)
protected override IEnumerable<string> GetImplementedInterfaces(IEntityGenerationModel entityGenerationModel)
{
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace Dhgms.Nucleotide.Generators.Features.EntityFramework
/// </summary>
public abstract class EntityFrameworkDbContextGenerator : BaseGenerator<EntityFrameworkDbContextFeatureFlags, EntityFrameworkDbContextGeneratorProcessor, IEntityGenerationModel>
{
///<inheritdoc />
protected override string GetNamespace()
{
return "EfModels";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace Dhgms.Nucleotide.Generators.Features.EntityFramework
/// </summary>
public sealed class EntityFrameworkDbContextGeneratorProcessor : BaseGeneratorProcessor<IEntityGenerationModel>
{
///<inheritdoc />
public override NamespaceDeclarationSyntax GenerateObjects(
NamespaceDeclarationSyntax namespaceDeclaration,
INucleotideGenerationModel<IEntityGenerationModel> nucleotideGenerationModel)
Expand Down Expand Up @@ -151,7 +152,7 @@ private PropertyDeclarationSyntax[] GetPropertyDeclarations(IEntityGenerationMod

var summary = GetSummary(new[] { $"Gets or Sets the DBSet for {generationModelEntityGenerationModel.ClassName}" });

var type = SyntaxFactory.ParseName($"DbSet<EfModels.{generationModelEntityGenerationModel.ClassName}EfModel>");
var type = SyntaxFactory.ParseTypeName($"DbSet<EfModels.{generationModelEntityGenerationModel.ClassName}EfModel>");
var identifier = generationModelEntityGenerationModel.ClassName;

var result = SyntaxFactory.PropertyDeclaration(type, identifier)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
using Dhgms.Nucleotide.Generators.Generators;
using Microsoft.CodeAnalysis;

namespace Dhgms.Nucleotide.Generators.Features.EntityFramework
{
public abstract class EntityFrameworkEntityTypeConfigurationGenerator : BaseClassLevelCodeGenerator<EntityFrameworkEntityTypeConfigurationFeatureFlags, EntityFrameworkEntityTypeConfigurationGeneratorProcessor>
public abstract class EntityFrameworkEntityTypeConfigurationGenerator : BaseClassLevelCodeGenerator<EntityFrameworkEntityTypeConfigurationFeatureFlags, EntityFrameworkEntityTypeConfigurationGeneratorProcessor, EntityFrameworkModelEntityGenerationModel>
{
///<inheritdoc />
protected override string GetNamespace()
{
return "EntityTypeConfigurations";
Expand Down
Loading

0 comments on commit 1acfd29

Please sign in to comment.