JD.Efcpt.Build supports T4 (Text Template Transformation Toolkit) templates for customizing code generation. This guide explains how to use and customize templates.
T4 templates let you control exactly how your DbContext and entity classes are generated. You can:
- Change the coding style and formatting
- Add custom attributes or annotations
- Include additional methods or properties
- Generate partial classes with custom logic
- Apply your organization's coding standards
Add to your efcpt-config.json:
{
"code-generation": {
"use-t4": true,
"t4-template-path": "."
}
}The t4-template-path is relative to the configuration file location.
Create the template folder structure in your project:
YourProject/
├── YourProject.csproj
├── efcpt-config.json
└── Template/
└── CodeTemplates/
└── EFCore/
├── DbContext.t4
└── EntityType.t4
Or use a simpler structure:
YourProject/
├── YourProject.csproj
├── efcpt-config.json
└── CodeTemplates/
└── EFCore/
├── DbContext.t4
└── EntityType.t4
Copy the default templates from EF Core Power Tools or create your own. The minimum required templates are:
DbContext.t4- Generates the DbContext classEntityType.t4- Generates entity classes
The StageEfcptInputs task understands several common layouts:
Template/
└── CodeTemplates/
└── EFCore/
├── DbContext.t4
└── EntityType.t4
The task copies CodeTemplates to the staging directory.
CodeTemplates/
└── EFCore/
├── DbContext.t4
└── EntityType.t4
The entire CodeTemplates tree is copied.
MyTemplates/
├── DbContext.t4
└── EntityType.t4
The folder is staged as CodeTemplates.
During build, templates are staged to:
obj/efcpt/Generated/CodeTemplates/EFCore/
├── DbContext.t4
└── EntityType.t4
This ensures:
- Consistent paths for efcpt CLI
- Clean separation from source templates
- Correct fingerprinting for incremental builds
The DbContext.t4 template generates your DbContext class. Key customization points:
Adding custom using statements:
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using MyApp.Common; // Add your custom using
Adding custom methods:
<#
foreach (var entityType in Model.GetEntityTypes())
{
#>
public DbSet<<#= entityType.Name #>> <#= entityType.GetDbSetName() #> => Set<<#= entityType.Name #>>();
<#
}
#>
// Custom method
public async Task<int> SaveChangesWithAuditAsync(CancellationToken cancellationToken = default)
{
// Add audit logic
return await SaveChangesAsync(cancellationToken);
}
The EntityType.t4 template generates entity classes. Common customizations:
Adding custom attributes:
<#
var displayName = property.GetDisplayName();
if (!string.IsNullOrEmpty(displayName))
{
#>
[Display(Name = "<#= displayName #>")]
<#
}
#>
public <#= code.Reference(property.ClrType) #> <#= property.Name #> { get; set; }
Generating partial classes:
namespace <#= code.Namespace(entityType.GetNamespace(), Model) #>
{
public partial class <#= entityType.Name #>
{
// Generated properties
<#
foreach (var property in entityType.GetProperties())
{
#>
public <#= code.Reference(property.ClrType) #> <#= property.Name #> { get; set; }
<#
}
#>
}
}
In .csproj:
<PropertyGroup>
<EfcptTemplateDir>CustomTemplates</EfcptTemplateDir>
</PropertyGroup>Or in efcpt-config.json:
{
"code-generation": {
"use-t4": true,
"t4-template-path": "CustomTemplates"
}
}Templates are resolved in this order:
<EfcptTemplateDir>property (if set)Templatedirectory in project directoryTemplatedirectory in solution directory- Package default templates
/// <summary>
/// Gets or sets the <#= property.GetDisplayName() ?? property.Name #>.
/// </summary>
<#
if (property.GetComment() != null)
{
#>
/// <remarks>
/// <#= property.GetComment() #>
/// </remarks>
<#
}
#>
public <#= code.Reference(property.ClrType) #> <#= property.Name #> { get; set; }
namespace <#= code.Namespace(entityType.GetNamespace(), Model) #>
{
public partial class <#= entityType.Name #> : IEntity
{
// ... properties
}
}
<#
// Convert to camelCase for private fields
var fieldName = "_" + char.ToLower(property.Name[0]) + property.Name.Substring(1);
#>
private <#= code.Reference(property.ClrType) #> <#= fieldName #>;
public <#= code.Reference(property.ClrType) #> <#= property.Name #>
{
get => <#= fieldName #>;
set => <#= fieldName #> = value;
}
<#
var maxLength = property.GetMaxLength();
if (maxLength.HasValue)
{
#>
[MaxLength(<#= maxLength.Value #>)]
<#
}
if (!property.IsNullable)
{
#>
[Required]
<#
}
#>
public <#= code.Reference(property.ClrType) #> <#= property.Name #> { get; set; }
Templates have access to the EF Core model through the Model variable:
| Variable/Method | Description |
|---|---|
Model |
The full EF Core model |
Model.GetEntityTypes() |
All entity types in the model |
entityType.GetProperties() |
Properties of an entity |
entityType.GetNavigations() |
Navigation properties |
property.ClrType |
The CLR type of a property |
property.IsNullable |
Whether the property is nullable |
property.GetMaxLength() |
Maximum length constraint |
Verify:
use-t4is set totrueinefcpt-config.json- Template files exist in the expected location
- Template directory is correctly resolved (check with
EfcptDumpResolvedInputs)
<PropertyGroup>
<EfcptLogVerbosity>detailed</EfcptLogVerbosity>
<EfcptDumpResolvedInputs>true</EfcptDumpResolvedInputs>
</PropertyGroup>Template compilation errors appear in the build output. Common issues:
- Syntax errors in T4 directives
- Missing assembly references
- Incorrect namespace references
The fingerprint includes template files. If templates change, regeneration should occur automatically. If not:
# Force regeneration
rmdir /s /q obj\efcpt
dotnet build- Start with defaults - Copy default templates and modify incrementally
- Version control templates - Keep templates in source control alongside your project
- Test changes - Build after each template change to catch errors early
- Use partial classes - Generate partial classes to separate generated and custom code
- Document customizations - Comment your template modifications for team awareness
- Configuration - Complete configuration reference
- Advanced Topics - Multi-project and complex scenarios
- API Reference - MSBuild task documentation