Advanced Topics
This guide covers advanced patterns and configuration scenarios for JD.Efcpt.Build.
Multi-Project Solutions
In solutions with multiple projects that need EF Core model generation, you can centralize configuration using Directory.Build.props.
Shared Configuration
Create a Directory.Build.props file at the solution root:
<Project>
<PropertyGroup>
<!-- Enable for all projects by default -->
<EfcptEnabled>true</EfcptEnabled>
<!-- Consistent tool configuration -->
<EfcptToolMode>tool-manifest</EfcptToolMode>
<EfcptToolPackageId>ErikEJ.EFCorePowerTools.Cli</EfcptToolPackageId>
<EfcptToolVersion>10.*</EfcptToolVersion>
<!-- Logging -->
<EfcptLogVerbosity>minimal</EfcptLogVerbosity>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="JD.Efcpt.Build" Version="PACKAGE_VERSION" />
</ItemGroup>
</Project>
Individual projects can override specific settings:
<!-- src/MyApp/MyApp.csproj -->
<PropertyGroup>
<EfcptSqlProj>..\..\database\MyDatabase\MyDatabase.sqlproj</EfcptSqlProj>
<EfcptConfig>my-specific-config.json</EfcptConfig>
</PropertyGroup>
Disabling for Specific Projects
Some projects may not need model generation. Disable it explicitly:
<!-- src/Tests/Tests.csproj -->
<PropertyGroup>
<EfcptEnabled>false</EfcptEnabled>
</PropertyGroup>
Or conditionally disable for test projects:
<!-- Directory.Build.props -->
<PropertyGroup Condition="$(MSBuildProjectName.EndsWith('.Tests'))">
<EfcptEnabled>false</EfcptEnabled>
</PropertyGroup>
Configuration-Based Switching
Different Configurations per Environment
Use MSBuild conditions to switch database sources by configuration:
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<EfcptConnectionString>Server=localhost;Database=MyDb_Dev;Integrated Security=True;</EfcptConnectionString>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<EfcptSqlProj>..\database\MyDatabase.sqlproj</EfcptSqlProj>
</PropertyGroup>
Disable for Specific Configurations
Disable model generation entirely for certain configurations:
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
<EfcptEnabled>false</EfcptEnabled>
</PropertyGroup>
Working with Multiple Databases
Generating from Multiple Sources
If you need models from multiple databases, create separate projects:
MySolution/
├── src/
│ ├── MyApp.Core/ # Business logic
│ ├── MyApp.Data.Primary/ # Primary database models
│ │ └── efcpt-config.json
│ └── MyApp.Data.Reporting/ # Reporting database models
│ └── efcpt-config.json
└── database/
├── Primary.sqlproj
└── Reporting.sqlproj
Each data project has its own configuration:
<!-- MyApp.Data.Primary.csproj -->
<PropertyGroup>
<EfcptSqlProj>..\..\database\Primary.sqlproj</EfcptSqlProj>
</PropertyGroup>
<!-- MyApp.Data.Reporting.csproj -->
<PropertyGroup>
<EfcptSqlProj>..\..\database\Reporting.sqlproj</EfcptSqlProj>
</PropertyGroup>
Custom Output Locations
Changing the Generated Directory
By default, files are generated in obj/efcpt/Generated/. To change this:
<PropertyGroup>
<EfcptOutput>$(MSBuildProjectDirectory)\obj\custom-efcpt\</EfcptOutput>
<EfcptGeneratedDir>$(EfcptOutput)CustomGenerated\</EfcptGeneratedDir>
</PropertyGroup>
Generating to the Project Directory
While not recommended (generated files should typically be in obj/), you can generate to the project:
<PropertyGroup>
<EfcptGeneratedDir>$(MSBuildProjectDirectory)\Generated\</EfcptGeneratedDir>
</PropertyGroup>
Warning
Generating to the project directory means files will be included in source control unless explicitly ignored. The default obj/efcpt/ location is recommended.
Renaming Rules
Use efcpt.renaming.json to customize table and column names. The file is a JSON array organized by schema:
[
{
"SchemaName": "dbo",
"Tables": [
{
"Name": "tblUsers",
"NewName": "User",
"Columns": [
{
"Name": "usr_id",
"NewName": "Id"
},
{
"Name": "usr_email",
"NewName": "Email"
}
]
},
{
"Name": "tblOrders",
"NewName": "Order"
}
],
"UseSchemaName": false
}
]
Resolution Order
Renaming files are resolved in this order:
<EfcptRenaming>property (if set)efcpt.renaming.jsonin project directoryefcpt.renaming.jsonin solution directory- Package default (empty renaming rules)
Diagnostic Logging
Enabling Detailed Logs
For troubleshooting, enable detailed logging:
<PropertyGroup>
<EfcptLogVerbosity>detailed</EfcptLogVerbosity>
<EfcptDumpResolvedInputs>true</EfcptDumpResolvedInputs>
</PropertyGroup>
This outputs:
- All resolved input paths
- Fingerprint computation details
- CLI invocation commands
- Detailed error messages
Inspecting Resolved Inputs
When EfcptDumpResolvedInputs is true, a resolved-inputs.json file is written to obj/efcpt/:
{
"sqlProjPath": "..\\database\\MyDatabase.sqlproj",
"configPath": "efcpt-config.json",
"renamingPath": "efcpt.renaming.json",
"templateDir": "Template",
"connectionString": null,
"useConnectionString": false
}
Working with DACPAC Build
Using a Pre-built DACPAC
If you have a pre-built DACPAC file, you can point to it directly:
<PropertyGroup>
<EfcptDacpac>path\to\MyDatabase.dacpac</EfcptDacpac>
</PropertyGroup>
When EfcptDacpac is set, the package skips the .sqlproj build step and uses the specified DACPAC directly.
DACPAC Build Configuration
Control how the .sqlproj is built:
<PropertyGroup>
<!-- Use specific MSBuild executable -->
<EfcptMsBuildExe>C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\MSBuild.exe</EfcptMsBuildExe>
<!-- Use specific dotnet executable -->
<EfcptDotNetExe>C:\dotnet\dotnet.exe</EfcptDotNetExe>
</PropertyGroup>
Modern SQL SDK Projects
JD.Efcpt.Build supports modern SQL SDK projects that use Microsoft.Build.Sql or MSBuild.Sdk.SqlProj:
<!-- Modern SDK-style SQL project -->
<Project Sdk="MSBuild.Sdk.SqlProj/2.8.1">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<SqlServerVersion>Sql160</SqlServerVersion>
</PropertyGroup>
</Project>
The package automatically detects these projects and handles them appropriately.
Excluding Tables and Schemas
Use efcpt-config.json to control what's included in generation:
{
"table-selection": [
{
"schema": "dbo",
"include": true
},
{
"schema": "audit",
"include": false
},
{
"schema": "dbo",
"tables": ["__EFMigrationsHistory"],
"include": false
}
]
}
This includes all dbo schema tables except __EFMigrationsHistory, and excludes the entire audit schema.
Handling Large Databases
Selecting Specific Tables
For large databases, explicitly select tables to generate:
{
"table-selection": [
{
"schema": "dbo",
"tables": ["Users", "Orders", "Products"],
"include": true
}
]
}
Splitting by Schema
Use schema-based organization to manage large models:
{
"file-layout": {
"use-schema-folders-preview": true,
"use-schema-namespaces-preview": true
}
}
Error Recovery
Handling Failed Builds
If model generation fails, previous generated files remain. To start fresh:
# Delete intermediate directory
rmdir /s /q obj\efcpt
# Clean build
dotnet clean
dotnet build
Inspecting Build Logs
Check MSBuild logs for detailed error information:
dotnet build /v:detailed > build.log
Look for JD.Efcpt.Build entries in the log.
Source Control Integration
Recommended .gitignore
Add these patterns to your .gitignore:
# JD.Efcpt.Build generated files
obj/efcpt/
*.g.cs
Checking in Generated Files
If you need to check in generated files (not recommended), generate to a project directory:
<PropertyGroup>
<EfcptGeneratedDir>$(MSBuildProjectDirectory)\Generated\</EfcptGeneratedDir>
</PropertyGroup>
Remove *.g.cs from .gitignore.
Performance Optimization
Reducing Build Time
- Use fingerprinting - Don't delete
obj/efcpt/unnecessarily - Use connection string mode - Skips DACPAC build step
- Select specific tables - Don't generate unused entities
- Use parallel builds - The package supports parallel project builds
Caching in CI/CD
Cache the obj/efcpt/ directory between builds to avoid regeneration:
# GitHub Actions
- uses: actions/cache@v3
with:
path: |
**/obj/efcpt/
key: efcpt-${{ hashFiles('**/*.sqlproj') }}-${{ hashFiles('**/efcpt-config.json') }}
Next Steps
- Troubleshooting - Solve common problems
- API Reference - Complete property and task reference
- CI/CD Integration - Deploy in automated pipelines