Skip to content

Commit

Permalink
Add support for prefix naming in EF Core 8
Browse files Browse the repository at this point in the history
relates to #2143
  • Loading branch information
ErikEJ committed Feb 6, 2024
1 parent 952e326 commit d446be6
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 3 deletions.
89 changes: 87 additions & 2 deletions src/Core/RevEng.Core.60/ReplacingCandidateNamingService.cs
@@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore.Scaffolding.Internal;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Scaffolding.Internal;
using Microsoft.EntityFrameworkCore.Scaffolding.Metadata;
using RevEng.Common;
using System;
Expand All @@ -13,11 +14,16 @@ public class ReplacingCandidateNamingService : CandidateNamingService
{
private readonly List<Schema> customNameOptions;
private readonly bool preserveCasingUsingRegex;
private readonly bool usePrefixNaming;

public ReplacingCandidateNamingService(List<Schema> customNameOptions, bool preserveCasingUsingRegex = false)
public ReplacingCandidateNamingService(
List<Schema> customNameOptions,
bool preserveCasingUsingRegex = false,
bool usePrefixNaming = false)
{
this.customNameOptions = customNameOptions;
this.preserveCasingUsingRegex = preserveCasingUsingRegex;
this.usePrefixNaming = usePrefixNaming;
}

public override string GenerateCandidateIdentifier(DatabaseTable originalTable)
Expand Down Expand Up @@ -129,6 +135,85 @@ public override string GenerateCandidateIdentifier(DatabaseColumn originalColumn
return base.GenerateCandidateIdentifier(originalColumn);
}

#if CORE80
public override string GetDependentEndCandidateNavigationPropertyName(IReadOnlyForeignKey foreignKey)
{
ArgumentNullException.ThrowIfNull(foreignKey);

if (!usePrefixNaming)
{
return base.GetDependentEndCandidateNavigationPropertyName(foreignKey);
}

var candidateName = FindCandidateNavigationName(foreignKey.Properties);

return !string.IsNullOrEmpty(candidateName) ? candidateName : foreignKey.PrincipalEntityType.ShortName();
}

private static string FindCandidateNavigationName(IEnumerable<IReadOnlyProperty> properties)
{
var count = properties.Count();
if (count == 0)
{
return string.Empty;
}

var firstProperty = properties.First();
return StripId(
count == 1
? firstProperty.Name
: FindCommonPrefix(firstProperty.Name, properties.Select(p => p.Name)));
}

private static string FindCommonPrefix(string firstName, IEnumerable<string> propertyNames)
{
var prefixLength = 0;
foreach (var c in firstName)
{
foreach (var s in propertyNames)
{
if (s.Length <= prefixLength
|| s[prefixLength] != c)
{
return firstName[..prefixLength];
}
}

prefixLength++;
}

return firstName[..prefixLength];
}

private static string StripId(string commonPrefix)
{
if (commonPrefix.Length < 3
|| !commonPrefix.EndsWith("id", StringComparison.OrdinalIgnoreCase))
{
return commonPrefix;
}

var ignoredCharacterCount = 2;
if (commonPrefix.Length > 4
&& commonPrefix.EndsWith("guid", StringComparison.OrdinalIgnoreCase))
{
ignoredCharacterCount = 4;
}

int i;
for (i = commonPrefix.Length - ignoredCharacterCount - 1; i >= 0; i--)
{
if (char.IsLetterOrDigit(commonPrefix[i]))
{
break;
}
}

return i != 0
? commonPrefix[..(i + 1)]
: commonPrefix;
}
#endif
private static string GenerateIdentifier(string value)
{
var candidateStringBuilder = new StringBuilder();
Expand Down
8 changes: 7 additions & 1 deletion src/Core/RevEng.Core.60/ServiceProviderBuilder.cs
Expand Up @@ -59,11 +59,17 @@ public static IServiceCollection AddEfpt(this IServiceCollection serviceCollecti
options.DatabaseType,
options.UseManyToManyEntity));

#if CORE80
if (options.CustomReplacers != null || options.UsePrefixNavigationNaming)
{
serviceCollection.AddSingleton<ICandidateNamingService>(provider => new ReplacingCandidateNamingService(options.CustomReplacers, options.PreserveCasingWithRegex, options.UsePrefixNavigationNaming));
}
#else
if (options.CustomReplacers != null)
{
serviceCollection.AddSingleton<ICandidateNamingService>(provider => new ReplacingCandidateNamingService(options.CustomReplacers, options.PreserveCasingWithRegex));
}

#endif
if (options.UseHandleBars)
{
serviceCollection.AddHandlebarsScaffolding(hbOptions =>
Expand Down
1 change: 1 addition & 0 deletions src/GUI/RevEng.Shared/ReverseEngineerCommandOptions.cs
Expand Up @@ -59,5 +59,6 @@ public class ReverseEngineerCommandOptions
public bool UseDecimalDataAnnotation { get; set; }
public bool PreserveCasingWithRegex { get; set; }
public bool UseDateOnlyTimeOnly { get; set; }
public bool UsePrefixNavigationNaming { get; set; }
}
}
Expand Up @@ -114,6 +114,7 @@ public static async Task<ReverseEngineerResult> LaunchExternalRunnerAsync(Revers
UseDateOnlyTimeOnly = options.UseDateOnlyTimeOnly,
UseSchemaNamespaces = options.UseSchemaNamespaces,
UseDecimalDataAnnotation = options.UseDecimalDataAnnotationForSprocResult,
UsePrefixNavigationNaming = options.UsePrefixNavigationNaming,
};

var launcher = new EfRevEngLauncher(commandOptions, codeGenerationMode);
Expand Down
Expand Up @@ -60,5 +60,6 @@ public class ReverseEngineerOptions
public bool UseDateOnlyTimeOnly { get; set; }
public string T4TemplatePath { get; set; }
public bool UseDecimalDataAnnotationForSprocResult { get; set; } = true;
public bool UsePrefixNavigationNaming { get; set; }
}
}
Binary file modified src/GUI/lib/efreveng80.exe.zip
Binary file not shown.

0 comments on commit d446be6

Please sign in to comment.