Skip to content

Commit f52f9da

Browse files
authored
WIP: Adds support for Using EntityTypeConfiguration files. (#2582)
* Adds support for Using EntityTypeConfiguration files. * Fix code smells * Adds new use-t4-split option. Adds example t4's configured for EntityTypeConfiguraiton usage. adds warning if you try to use use-t4 and use-t4-split. Adds warning if you try to use use-t4 and split-dbcontext-preview. * Fix version for EntityTypeConfiguraiton to 8. * Fixes T800 Zip file nesting. Adds T800 Zip File unzipping for CLI. * PR Feedback. Adds use-t4-split to the VS schema json. Moves the warnings about use-t4-split + use-t4 to ReverseEngineerRunner Fxes UseT4Split JsonPropertyOrder being the same as UseT4 Removes sample EntityTypeConfiguration now that it exists in the 800_split folder.
1 parent bb0db72 commit f52f9da

17 files changed

+891
-12
lines changed

samples/efcpt-config.schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,11 @@
217217
"type": "boolean",
218218
"title": "Customize code using T4 templates"
219219
},
220+
"use-t4-split": {
221+
"type": "boolean",
222+
"default": false,
223+
"title": "Customize code using T4 templates including EntityTypeConfiguration.t4. This cannot be used in combination with use-t4 or split-dbcontext-preview"
224+
},
220225
"remove-defaultsql-from-bool-properties": {
221226
"type": "boolean",
222227
"title": "Remove SQL default from bool columns to avoid them being bool?"

samples/efcpt-schema.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,14 @@
377377
false
378378
]
379379
},
380+
"use-t4-split": {
381+
"type": "boolean",
382+
"default": false,
383+
"title": "Customize code using T4 templates including EntityTypeConfiguration.t4. This cannot be used in combination with use-t4 or split-dbcontext-preview",
384+
"examples": [
385+
false
386+
]
387+
},
380388
"t4-template-path": {
381389
"type": [ "string", "null" ] ,
382390
"default": null,

src/Core/RevEng.Core.60/IReverseEngineerScaffolder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace RevEng.Core
66
{
77
public interface IReverseEngineerScaffolder
88
{
9-
SavedModelFiles GenerateDbContext(ReverseEngineerCommandOptions options, List<string> schemas, string outputContextDir, string modelNamespace, string contextNamespace, string projectPath, string outputPath);
9+
SavedModelFiles GenerateDbContext(ReverseEngineerCommandOptions options, List<string> schemas, string outputContextDir, string modelNamespace, string contextNamespace, string projectPath, string outputPath, string rootNameSpace);
1010
SavedModelFiles GenerateFunctions(ReverseEngineerCommandOptions options, List<string> schemas, ref List<string> errors, string outputContextDir, string modelNamespace, string contextNamespace, bool supportsFunctions);
1111
SavedModelFiles GenerateStoredProcedures(ReverseEngineerCommandOptions options, List<string> schemas, ref List<string> errors, string outputContextDir, string modelNamespace, string contextNamespace, bool supportsProcedures);
1212
}

src/Core/RevEng.Core.60/ReverseEngineerRunner.cs

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,14 @@ public static ReverseEngineerResult GenerateFiles(ReverseEngineerCommandOptions
8383

8484
try
8585
{
86-
SavedModelFiles filePaths = scaffolder!.GenerateDbContext(options, schemas, outputContextDir, modelNamespace, contextNamespace, options.ProjectPath, options.OutputPath);
86+
SavedModelFiles filePaths = scaffolder!.GenerateDbContext(options, schemas, outputContextDir, modelNamespace, contextNamespace, options.ProjectPath, options.OutputPath, options.ProjectRootNamespace);
8787

8888
#if CORE70 || CORE80
89-
if (options.UseT4)
89+
if (options.UseT4 || options.UseT4Split)
9090
{
9191
foreach (var paths in GetAlternateCodeTemplatePaths(options.ProjectPath))
9292
{
93-
scaffolder!.GenerateDbContext(options, schemas, paths.Path, modelNamespace, contextNamespace, paths.Path, paths.OutputPath);
93+
scaffolder!.GenerateDbContext(options, schemas, paths.Path, modelNamespace, contextNamespace, paths.Path, paths.OutputPath, options.ProjectRootNamespace);
9494
}
9595
}
9696
#endif
@@ -139,20 +139,25 @@ public static ReverseEngineerResult GenerateFiles(ReverseEngineerCommandOptions
139139
}
140140

141141
RemoveFragments(filePaths.ContextFile, options.ContextClassName, options.IncludeConnectionString, options.UseNoDefaultConstructor);
142-
if (!options.UseHandleBars && !options.UseT4)
142+
if (!options.UseHandleBars && !options.UseT4 && !options.UseT4Split)
143143
{
144144
PostProcess(filePaths.ContextFile, options.UseNullableReferences);
145145
}
146146

147147
entityTypeConfigurationPaths = SplitDbContext(filePaths.ContextFile, options.UseDbContextSplitting, contextNamespace, options.UseNullableReferences, options.ContextClassName);
148+
149+
if (options.UseT4Split)
150+
{
151+
entityTypeConfigurationPaths.AddRange(MoveConfigurationFiles(filePaths.AdditionalFiles));
152+
}
148153
}
149154
else if (options.Tables.Exists(t => t.ObjectType == ObjectType.Procedure)
150155
|| options.Tables.Exists(t => t.ObjectType == ObjectType.ScalarFunction))
151156
{
152157
warnings.Add("Selected stored procedures/scalar functions will not be generated, as 'Entity Types only' was selected");
153158
}
154159

155-
if (!options.UseHandleBars && !options.UseT4)
160+
if (!options.UseHandleBars && !options.UseT4 && !options.UseT4Split)
156161
{
157162
foreach (var file in filePaths.AdditionalFiles)
158163
{
@@ -193,6 +198,18 @@ public static ReverseEngineerResult GenerateFiles(ReverseEngineerCommandOptions
193198
warnings.Add($"'use-database-names' / 'UseDatabaseNames' has been set to true, but a '{Constants.RenamingFileName}' file was also found. This prevents '{Constants.RenamingFileName}' from functioning.");
194199
}
195200

201+
if (options.UseT4 && options.UseT4Split)
202+
{
203+
warnings.Add("Both UseT4 and UseT4Split are set to true. Only one of thse should be used, UseT4Split will be ignored.");
204+
options.UseT4Split = false;
205+
}
206+
207+
if (options.UseT4Split && options.UseDbContextSplitting)
208+
{
209+
warnings.Add("Both UseDbContextSplitting and UseT4Split are set to true. Only one of thse should be used, UseT4Split will be ignored.");
210+
options.UseT4Split = false;
211+
}
212+
196213
var result = new ReverseEngineerResult
197214
{
198215
EntityErrors = errors,
@@ -323,6 +340,22 @@ private static List<string> SplitDbContext(string contextFile, bool useDbContext
323340
return DbContextSplitter.Split(contextFile, contextNamespace, supportNullable, dbContextName);
324341
}
325342

343+
// If we didn't split, we might have used EntityTypeConfiguration.t4. In that case, <ModelName>Configuration.cs files were generated.
344+
private static List<string> MoveConfigurationFiles(IList<string> files)
345+
{
346+
var configurationFiles = files.Where(x => x.EndsWith("Configuration.cs", StringComparison.InvariantCulture)).ToList();
347+
348+
var movedFiles = new List<string>();
349+
foreach (var configurationFile in configurationFiles)
350+
{
351+
var newFileName = Path.Combine(Path.GetDirectoryName(configurationFile) ?? string.Empty, "Configurations", Path.GetFileName(configurationFile));
352+
File.Move(configurationFile, newFileName, overwrite: true);
353+
movedFiles.Add(newFileName);
354+
}
355+
356+
return movedFiles;
357+
}
358+
326359
private static void RemoveFragments(string contextFile, string contextName, bool includeConnectionString, bool removeDefaultConstructor)
327360
{
328361
if (string.IsNullOrEmpty(contextFile))

src/Core/RevEng.Core.60/ReverseEngineerScaffolder.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ public SavedModelFiles GenerateDbContext(
5959
string modelNamespace,
6060
string contextNamespace,
6161
string projectPath,
62-
string outputPath)
62+
string outputPath,
63+
string rootNameSpace)
6364
{
6465
ArgumentNullException.ThrowIfNull(options);
6566

@@ -77,15 +78,15 @@ public SavedModelFiles GenerateDbContext(
7778

7879
ContextName = code.Identifier(options.ContextClassName),
7980
ContextDir = outputContextDir,
80-
RootNamespace = null,
81+
RootNamespace = rootNameSpace,
8182
ContextNamespace = contextNamespace,
8283
ModelNamespace = modelNamespace,
8384
SuppressConnectionStringWarning = false,
8485
ConnectionString = options.ConnectionString,
8586
SuppressOnConfiguring = !options.IncludeConnectionString,
8687
UseNullableReferenceTypes = options.UseNullableReferences,
8788
#if CORE70 || CORE80
88-
ProjectDir = options.UseT4 ? (options.T4TemplatePath ?? projectPath) : null,
89+
ProjectDir = (options.UseT4 || options.UseT4Split) ? (options.T4TemplatePath ?? projectPath) : null,
8990
#endif
9091
};
9192

src/Core/efcpt.8/HostedServices/ScaffoldHostedService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,9 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
7474

7575
#pragma warning disable S2589 // Boolean expressions should not be gratuitous
7676
#pragma warning disable S2583 // Conditionally executed code should be reachable
77-
if (commandOptions.UseT4 && Constants.Version > 6)
77+
if ((commandOptions.UseT4 || commandOptions.UseT4Split) && Constants.Version > 6)
7878
{
79-
var t4Result = T4Helper.DropT4Templates(commandOptions.T4TemplatePath ?? commandOptions.ProjectPath, Constants.CodeGeneration);
79+
var t4Result = T4Helper.DropT4Templates(commandOptions.T4TemplatePath ?? commandOptions.ProjectPath, Constants.CodeGeneration, commandOptions.UseT4Split);
8080
if (!string.IsNullOrEmpty(t4Result))
8181
{
8282
DisplayService.MarkupLine(t4Result, Color.Default);

src/Core/efcpt.8/efcpt.8.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
<Content Include="..\..\GUI\lib\T4_800.zip" Link="T4_800.zip">
3535
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
3636
</Content>
37+
<Content Include="..\..\GUI\lib\T4_800_Split.zip" Link="T4_800_Split.zip">
38+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
39+
</Content>
3740
<Content Include="efcpt-readme.md">
3841
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
3942
</Content>

src/GUI/RevEng.Shared/Cli/CliConfigMapper.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ public static ReverseEngineerCommandOptions ToCommandOptions(
7272
UseInflector = config.CodeGeneration.UseInflector,
7373
UseT4 = config.CodeGeneration.UseT4,
7474
T4TemplatePath = config.CodeGeneration.T4TemplatePath != null ? PathHelper.GetAbsPath(config.CodeGeneration.T4TemplatePath, projectPath) : null,
75+
UseT4Split = config.CodeGeneration.UseT4Split,
7576
IncludeConnectionString = !isDacpac && config.CodeGeneration.EnableOnConfiguring,
7677
SelectedToBeGenerated = selectedToBeGenerated,
7778
Dacpac = isDacpac ? connectionString : null,

src/GUI/RevEng.Shared/Cli/Configuration/CodeGeneration.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,5 +85,9 @@ public class CodeGeneration
8585
[JsonPropertyOrder(200)]
8686
[JsonPropertyName("use-t4")]
8787
public bool UseT4 { get; set; }
88+
89+
[JsonPropertyOrder(210)]
90+
[JsonPropertyName("use-t4-split")]
91+
public bool UseT4Split { get; set; }
8892
}
8993
}

src/GUI/RevEng.Shared/Cli/T4Helper.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace RevEng.Common.Cli
88
{
99
public static class T4Helper
1010
{
11-
public static string DropT4Templates(string projectPath, CodeGenerationMode codeGenerationMode)
11+
public static string DropT4Templates(string projectPath, CodeGenerationMode codeGenerationMode, bool useEntityTypeSplitting = false)
1212
{
1313
string t4Version = "703";
1414

@@ -22,6 +22,11 @@ public static string DropT4Templates(string projectPath, CodeGenerationMode code
2222
t4Version = "900";
2323
}
2424

25+
if (useEntityTypeSplitting)
26+
{
27+
t4Version += "_Split";
28+
}
29+
2530
var zipName = $"T4_{t4Version}.zip";
2631

2732
var toDir = Path.Combine(projectPath, "CodeTemplates");
@@ -57,6 +62,16 @@ public static string DropT4Templates(string projectPath, CodeGenerationMode code
5762
return error;
5863
}
5964
}
65+
66+
target = Path.Combine(toDir, "EFCore", "EntityTypeConfiguration.t4");
67+
if (File.Exists(target))
68+
{
69+
var content = File.ReadAllText(target, Encoding.UTF8);
70+
if (content.IndexOf(check, StringComparison.OrdinalIgnoreCase) == -1)
71+
{
72+
return error;
73+
}
74+
}
6075
}
6176

6277
return string.Empty;

src/GUI/RevEng.Shared/ReverseEngineerCommandOptions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public class ReverseEngineerCommandOptions
3131
public bool UseHandleBars { get; set; }
3232
public bool UseT4 { get; set; }
3333
public string T4TemplatePath { get; set; }
34+
public bool UseT4Split { get; set; }
3435
public int SelectedHandlebarsLanguage { get; set; }
3536
public bool IncludeConnectionString { get; set; }
3637
public int SelectedToBeGenerated { get; set; }

src/GUI/RevEng.Shared/ReverseEngineerOptions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public class ReverseEngineerOptions
2929
public List<string> UncountableWords { get; set; }
3030
public bool UseHandleBars { get; set; }
3131
public bool UseT4 { get; set; }
32+
public bool UseT4Split { get; set; }
3233
public int SelectedHandlebarsLanguage { get; set; } = 2;
3334
public bool IncludeConnectionString { get; set; }
3435
public int SelectedToBeGenerated { get; set; }

src/GUI/Shared/Handlers/ReverseEngineer/EfRevEngLauncher.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ public static async Task<ReverseEngineerResult> LaunchExternalRunnerAsync(Revers
9595
UseHandleBars = options.UseHandleBars,
9696
UseT4 = options.UseT4,
9797
T4TemplatePath = options.T4TemplatePath != null ? PathHelper.GetAbsPath(options.T4TemplatePath, options.ProjectPath) : null,
98+
UseT4Split = options.UseT4Split,
9899
UseInflector = options.UseInflector,
99100
UseLegacyPluralizer = options.UseLegacyPluralizer,
100101
UncountableWords = options.UncountableWords,

src/GUI/lib/T4_800_Split.zip

7.04 KB
Binary file not shown.

0 commit comments

Comments
 (0)