Created
November 20, 2022 10:54
-
-
Save marcominerva/5e42a6d3493cfe2a0a84d29ce5727932 to your computer and use it in GitHub Desktop.
The T4 template to create Entity Configuration classes: https://learn.microsoft.com/en-us/ef/core/managing-schemas/scaffolding/templates?tabs=dotnet-core-cli#entity-configuration-classes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<#@ template hostSpecific="true" debug="false" #> | |
<#@ assembly name="Microsoft.EntityFrameworkCore" #> | |
<#@ assembly name="Microsoft.EntityFrameworkCore.Design" #> | |
<#@ assembly name="Microsoft.EntityFrameworkCore.Relational" #> | |
<#@ assembly name="Microsoft.Extensions.DependencyInjection.Abstractions" #> | |
<#@ parameter name="EntityType" type="Microsoft.EntityFrameworkCore.Metadata.IEntityType" #> | |
<#@ parameter name="Options" type="Microsoft.EntityFrameworkCore.Scaffolding.ModelCodeGenerationOptions" #> | |
<#@ parameter name="NamespaceHint" type="System.String" #> | |
<#@ parameter name="ProjectDefaultNamespace" type="System.String" #> | |
<#@ import namespace="System.Collections.Generic" #> | |
<#@ import namespace="System.Linq" #> | |
<#@ import namespace="System.Text" #> | |
<#@ import namespace="Microsoft.EntityFrameworkCore" #> | |
<#@ import namespace="Microsoft.EntityFrameworkCore.Design" #> | |
<#@ import namespace="Microsoft.EntityFrameworkCore.Infrastructure" #> | |
<#@ import namespace="Microsoft.EntityFrameworkCore.Scaffolding" #> | |
<#@ import namespace="Microsoft.Extensions.DependencyInjection" #> | |
<#@ import namespace="Microsoft.EntityFrameworkCore.Metadata.Builders" #> | |
<# | |
if (!ProductInfo.GetVersion().StartsWith("7.0")) | |
{ | |
Warning("Your templates were created using an older version of Entity Framework. Additional features and bug fixes may be available. See https://aka.ms/efcore-docs-updating-templates for more information."); | |
} | |
var services = (IServiceProvider)Host; | |
var providerCode = services.GetRequiredService<IProviderConfigurationCodeGenerator>(); | |
var annotationCodeGenerator = services.GetRequiredService<IAnnotationCodeGenerator>(); | |
var code = services.GetRequiredService<ICSharpHelper>(); | |
var usings = new List<string> | |
{ | |
"System", | |
"System.Collections.Generic", | |
"Microsoft.EntityFrameworkCore" | |
}; | |
if (NamespaceHint != Options.ModelNamespace | |
&& !string.IsNullOrEmpty(Options.ModelNamespace)) | |
{ | |
usings.Add(Options.ModelNamespace); | |
} | |
usings.Add(typeof(EntityTypeBuilder<>).Namespace); | |
if (!string.IsNullOrEmpty(NamespaceHint)) | |
{ | |
#> | |
namespace <#= NamespaceHint #>; | |
<# | |
} | |
#> | |
public partial class <#= EntityType.Name #>Configuration : IEntityTypeConfiguration<<#= EntityType.Name #>> | |
{ | |
public void Configure(EntityTypeBuilder<<#= EntityType.Name #>> entity) | |
{ | |
<# | |
var anyConfiguration = false; | |
StringBuilder mainEnvironment; | |
if (EntityType?.Name!=null) | |
{ | |
// Save all previously generated code, and start generating into a new temporary environment | |
mainEnvironment = GenerationEnvironment; | |
GenerationEnvironment = new StringBuilder(); | |
var anyEntityTypeConfiguration = false; | |
var key = EntityType.FindPrimaryKey(); | |
if (key != null) | |
{ | |
var keyFluentApiCalls = key.GetFluentApiCalls(annotationCodeGenerator); | |
if (keyFluentApiCalls != null | |
|| (!key.IsHandledByConvention() && !Options.UseDataAnnotations)) | |
{ | |
if (keyFluentApiCalls != null) | |
{ | |
usings.AddRange(keyFluentApiCalls.GetRequiredUsings()); | |
} | |
#> | |
entity.HasKey(<#= code.Lambda(key.Properties, "e") #>)<#= code.Fragment(keyFluentApiCalls, indent: 3) #>; | |
<# | |
anyEntityTypeConfiguration = true; | |
} | |
} | |
var entityTypeFluentApiCalls = EntityType.GetFluentApiCalls(annotationCodeGenerator) | |
?.FilterChain(c => !(Options.UseDataAnnotations && c.IsHandledByDataAnnotations)); | |
if (entityTypeFluentApiCalls != null) | |
{ | |
usings.AddRange(entityTypeFluentApiCalls.GetRequiredUsings()); | |
if (anyEntityTypeConfiguration) | |
{ | |
WriteLine(""); | |
} | |
#> | |
entity<#= code.Fragment(entityTypeFluentApiCalls, indent: 3) #>; | |
<# | |
anyEntityTypeConfiguration = true; | |
} | |
foreach (var index in EntityType.GetIndexes() | |
.Where(i => !(Options.UseDataAnnotations && i.IsHandledByDataAnnotations(annotationCodeGenerator)))) | |
{ | |
if (anyEntityTypeConfiguration) | |
{ | |
WriteLine(""); | |
} | |
var indexFluentApiCalls = index.GetFluentApiCalls(annotationCodeGenerator); | |
if (indexFluentApiCalls != null) | |
{ | |
usings.AddRange(indexFluentApiCalls.GetRequiredUsings()); | |
} | |
#> | |
entity.HasIndex(<#= code.Lambda(index.Properties, "e") #>, <#= code.Literal(index.GetDatabaseName()) #>)<#= code.Fragment(indexFluentApiCalls, indent: 3) #>; | |
<# | |
anyEntityTypeConfiguration = true; | |
} | |
var firstProperty = true; | |
foreach (var property in EntityType.GetProperties()) | |
{ | |
var propertyFluentApiCalls = property.GetFluentApiCalls(annotationCodeGenerator) | |
?.FilterChain(c => !(Options.UseDataAnnotations && c.IsHandledByDataAnnotations) | |
&& !(c.Method == "IsRequired" && Options.UseNullableReferenceTypes && !property.ClrType.IsValueType)); | |
if (propertyFluentApiCalls == null) | |
{ | |
continue; | |
} | |
usings.AddRange(propertyFluentApiCalls.GetRequiredUsings()); | |
if (anyEntityTypeConfiguration && firstProperty) | |
{ | |
WriteLine(""); | |
} | |
#> | |
entity.Property(e => e.<#= property.Name #>)<#= code.Fragment(propertyFluentApiCalls, indent: 3) #>; | |
<# | |
anyEntityTypeConfiguration = true; | |
firstProperty = false; | |
} | |
foreach (var foreignKey in EntityType.GetForeignKeys()) | |
{ | |
var foreignKeyFluentApiCalls = foreignKey.GetFluentApiCalls(annotationCodeGenerator) | |
?.FilterChain(c => !(Options.UseDataAnnotations && c.IsHandledByDataAnnotations)); | |
if (foreignKeyFluentApiCalls == null) | |
{ | |
continue; | |
} | |
usings.AddRange(foreignKeyFluentApiCalls.GetRequiredUsings()); | |
if (anyEntityTypeConfiguration) | |
{ | |
WriteLine(""); | |
} | |
if (foreignKey.DependentToPrincipal?.Name != null && foreignKey.PrincipalToDependent?.Name != null) | |
{ | |
#> | |
entity.HasOne(d => d.<#= foreignKey.DependentToPrincipal.Name #>).<#= foreignKey.IsUnique ? "WithOne" : "WithMany" #>(p => p.<#= foreignKey.PrincipalToDependent.Name #>)<#= code.Fragment(foreignKeyFluentApiCalls, indent: 3) #>; | |
<# | |
} | |
anyEntityTypeConfiguration = true; | |
} | |
foreach (var skipNavigation in EntityType.GetSkipNavigations().Where(n => n.IsLeftNavigation())) | |
{ | |
if (anyEntityTypeConfiguration) | |
{ | |
WriteLine(""); | |
} | |
var left = skipNavigation.ForeignKey; | |
var leftFluentApiCalls = left.GetFluentApiCalls(annotationCodeGenerator, useStrings: true); | |
var right = skipNavigation.Inverse.ForeignKey; | |
var rightFluentApiCalls = right.GetFluentApiCalls(annotationCodeGenerator, useStrings: true); | |
var joinEntityType = skipNavigation.JoinEntityType; | |
if (leftFluentApiCalls != null) | |
{ | |
usings.AddRange(leftFluentApiCalls.GetRequiredUsings()); | |
} | |
if (rightFluentApiCalls != null) | |
{ | |
usings.AddRange(rightFluentApiCalls.GetRequiredUsings()); | |
} | |
#> | |
entity.HasMany(d => d.<#= skipNavigation.Name #>).WithMany(p => p.<#= skipNavigation.Inverse.Name #>) | |
.UsingEntity<Dictionary<string, object>>( | |
<#= code.Literal(joinEntityType.Name) #>, | |
r => r.HasOne<<#= right.PrincipalEntityType.Name #>>().WithMany()<#= code.Fragment(rightFluentApiCalls, indent: 6) #>, | |
l => l.HasOne<<#= left.PrincipalEntityType.Name #>>().WithMany()<#= code.Fragment(leftFluentApiCalls, indent: 6) #>, | |
j => | |
{ | |
<# | |
var joinKey = joinEntityType.FindPrimaryKey(); | |
var joinKeyFluentApiCalls = joinKey.GetFluentApiCalls(annotationCodeGenerator); | |
if (joinKeyFluentApiCalls != null) | |
{ | |
usings.AddRange(joinKeyFluentApiCalls.GetRequiredUsings()); | |
} | |
#> | |
j.HasKey(<#= code.Arguments(joinKey.Properties.Select(e => e.Name)) #>)<#= code.Fragment(joinKeyFluentApiCalls, indent: 7) #>; | |
<# | |
var joinEntityTypeFluentApiCalls = joinEntityType.GetFluentApiCalls(annotationCodeGenerator); | |
if (joinEntityTypeFluentApiCalls != null) | |
{ | |
usings.AddRange(joinEntityTypeFluentApiCalls.GetRequiredUsings()); | |
#> | |
j<#= code.Fragment(joinEntityTypeFluentApiCalls, indent: 7) #>; | |
<# | |
} | |
foreach (var index in joinEntityType.GetIndexes()) | |
{ | |
var indexFluentApiCalls = index.GetFluentApiCalls(annotationCodeGenerator); | |
if (indexFluentApiCalls != null) | |
{ | |
usings.AddRange(indexFluentApiCalls.GetRequiredUsings()); | |
} | |
#> | |
j.HasIndex(<#= code.Literal(index.Properties.Select(e => e.Name).ToArray()) #>, <#= code.Literal(index.GetDatabaseName()) #>)<#= code.Fragment(indexFluentApiCalls, indent: 7) #>; | |
<# | |
} | |
#> | |
}); | |
<# | |
anyEntityTypeConfiguration = true; | |
} | |
// If any significant code was generated, append it to the main environment | |
if (anyEntityTypeConfiguration) | |
{ | |
mainEnvironment.Append(GenerationEnvironment); | |
anyConfiguration = true; | |
} | |
// Resume generating code into the main environment | |
GenerationEnvironment = mainEnvironment; | |
} | |
if (anyConfiguration) | |
{ | |
WriteLine(""); | |
} | |
#> | |
OnConfigurePartial(entity); | |
} | |
partial void OnConfigurePartial(EntityTypeBuilder<<#= EntityType.Name #>> modelBuilder); | |
} | |
<# | |
mainEnvironment = GenerationEnvironment; | |
GenerationEnvironment = new StringBuilder(); | |
foreach (var ns in usings.Distinct().OrderBy(x => x, new NamespaceComparer())) | |
{ | |
#> | |
using <#= ns #>; | |
<# | |
} | |
WriteLine(""); | |
GenerationEnvironment.Append(mainEnvironment); | |
#> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment