diff --git a/.gitignore b/.gitignore
index 615ee80..1fd9da6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,4 +10,16 @@ docs/_site
coverage.cobertura.xml
pkg/
artifacts/
-*.bak
\ No newline at end of file
+*.bak
+tmpclaude-*
+tests/**/TestResults/
+
+# Auto-generated SQL files in samples
+# These are generated during build and should not be tracked
+samples/**/DatabaseProject/**/Tables/*.sql
+samples/**/DatabaseProject/**/Views/*.sql
+samples/**/DatabaseProject/**/StoredProcedures/*.sql
+samples/**/DatabaseProject/**/*.sql
+!samples/**/DatabaseProject/**/*.sqlproj
+!samples/**/DatabaseProject/**/*.csproj
+packages/
diff --git a/JD.Efcpt.Build.sln b/JD.Efcpt.Build.sln
index 1a2c7f2..7e06a0c 100644
--- a/JD.Efcpt.Build.sln
+++ b/JD.Efcpt.Build.sln
@@ -1,3 +1,4 @@
+
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
diff --git a/samples/NuGet.config b/samples/NuGet.config
new file mode 100644
index 0000000..03e648e
--- /dev/null
+++ b/samples/NuGet.config
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/samples/Samples.sln b/samples/Samples.sln
new file mode 100644
index 0000000..33dcab7
--- /dev/null
+++ b/samples/Samples.sln
@@ -0,0 +1,406 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31903.59
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "aspnet-core-appsettings", "aspnet-core-appsettings", "{1F87798A-3DA2-1D52-37E6-92287F21560B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetCoreAppSettings.AppHost", "aspnet-core-appsettings\AspNetCoreAppSettings.AppHost\AspNetCoreAppSettings.AppHost.csproj", "{50C548F6-BD90-44B2-939B-88E157BC1D77}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyApp.Api", "aspnet-core-appsettings\MyApp.Api\MyApp.Api.csproj", "{B6093DDC-14AF-4A21-989B-3AC63B89ACB0}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "connection-string-mssql", "connection-string-mssql", "{8FE76333-615D-4D0B-08EF-9ACA145B22E5}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConnectionStringMssql.AppHost", "connection-string-mssql\ConnectionStringMssql.AppHost\ConnectionStringMssql.AppHost.csproj", "{2809E8F4-B766-4D9D-B514-DEB85D974F5C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EntityFrameworkCoreProject", "connection-string-mssql\EntityFrameworkCoreProject\EntityFrameworkCoreProject.csproj", "{1ADB10A5-ABA0-430F-88EB-10D2F2A379FC}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "connection-string-sqlite", "connection-string-sqlite", "{F300D630-7571-566C-DE3A-0237458CBD19}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EntityFrameworkCoreProject", "connection-string-sqlite\EntityFrameworkCoreProject\EntityFrameworkCoreProject.csproj", "{D0DE0C4D-8901-4FBD-A78C-B11D1B4675B4}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "custom-renaming", "custom-renaming", "{10305151-72DA-BBBB-C817-BD890FA250F2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EntityFrameworkCoreProject", "custom-renaming\EntityFrameworkCoreProject\EntityFrameworkCoreProject.csproj", "{C7F9A6FC-67C8-4E44-B1CF-671A1315156D}"
+EndProject
+Project("{00D1A9C2-B5F0-4AF3-8072-F6C62B433612}") = "DatabaseProject", "custom-renaming\DatabaseProject\DatabaseProject.sqlproj", "{F00C8951-341A-4738-A289-33504D2906D5}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dacpac-zero-config", "dacpac-zero-config", "{CA0ABCE0-AAC8-D42B-D483-0AD6CB9ED44A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EntityFrameworkCoreProject", "dacpac-zero-config\EntityFrameworkCoreProject\EntityFrameworkCoreProject.csproj", "{D098CDA1-D567-45E4-8C0E-53DFBA25EE22}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "database-first-sql-generation", "database-first-sql-generation", "{46A6B6E4-1F62-AC21-FF7F-BCB260772A08}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataAccessProject", "database-first-sql-generation\DataAccessProject\DataAccessProject.csproj", "{E9BECDF9-5270-4E67-8B53-918DB5414427}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DatabaseProject", "database-first-sql-generation\DatabaseProject\DatabaseProject.csproj", "{FB8CDB1A-1DE0-488F-943A-115DE375344F}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "microsoft-build-sql-zero-config", "microsoft-build-sql-zero-config", "{D19774F8-5390-DECA-0D5D-DB3D3B1934CC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DatabaseProject", "microsoft-build-sql-zero-config\DatabaseProject\DatabaseProject.csproj", "{0756435B-A795-4CC3-BA73-E2AB0F436F39}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EntityFrameworkCoreProject", "microsoft-build-sql-zero-config\EntityFrameworkCoreProject\EntityFrameworkCoreProject.csproj", "{F03B61E0-1EB5-4ECB-8E43-1ED6A31E7665}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "msbuild-sdk-sql-proj-generation", "msbuild-sdk-sql-proj-generation", "{0FBFF59C-0FC2-5776-A3F6-C46E2EF347EC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DatabaseProject", "msbuild-sdk-sql-proj-generation\DatabaseProject\DatabaseProject.csproj", "{DA0491F2-641D-4E6D-9B97-DC465C1CCE33}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EntityFrameworkCoreProject", "msbuild-sdk-sql-proj-generation\EntityFrameworkCoreProject\EntityFrameworkCoreProject.csproj", "{DF6874DC-C650-43B5-AB7E-55CA87F7C515}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "schema-organization", "schema-organization", "{EBF3C506-8F29-9654-7600-23BD3F25C924}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EntityFrameworkCoreProject", "schema-organization\EntityFrameworkCoreProject\EntityFrameworkCoreProject.csproj", "{311609F6-420D-4B05-8E66-B1B084C45D19}"
+EndProject
+Project("{00D1A9C2-B5F0-4AF3-8072-F6C62B433612}") = "DatabaseProject", "schema-organization\DatabaseProject\DatabaseProject.sqlproj", "{433E6F74-5C51-43A5-A92C-C90D8DEB0D98}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sdk-zero-config", "sdk-zero-config", "{1B681BF4-A602-D408-2E69-2B57B87575B2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DatabaseProject", "sdk-zero-config\DatabaseProject\DatabaseProject.csproj", "{7973CB94-3824-48AD-816E-CD9EBF217B3A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EntityFrameworkCoreProject", "sdk-zero-config\EntityFrameworkCoreProject\EntityFrameworkCoreProject.csproj", "{E283EB20-A10D-482B-8320-93AFC70C36A8}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "simple-generation", "simple-generation", "{533FC926-FE64-7363-FF68-925D042523EE}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EntityFrameworkCoreProject", "simple-generation\EntityFrameworkCoreProject\EntityFrameworkCoreProject.csproj", "{C4A32153-A694-401F-B54A-38F7642D24D9}"
+EndProject
+Project("{00D1A9C2-B5F0-4AF3-8072-F6C62B433612}") = "DatabaseProject", "simple-generation\DatabaseProject\DatabaseProject.sqlproj", "{9F527768-04B3-4DED-89B7-0D0A8DA59DB9}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "simple-sql-integration", "simple-sql-integration", "{992222C4-ADE0-6BF1-7230-A9C65755AE09}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataAccessProject", "simple-sql-integration\DataAccessProject\DataAccessProject.csproj", "{E8265A69-7C88-4728-ACD2-710A5F7C0E3A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DatabaseProject", "simple-sql-integration\DatabaseProject\DatabaseProject.csproj", "{1B282238-83D7-4FBD-BE3C-180A82253543}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "split-data-and-models-between-multiple-projects", "split-data-and-models-between-multiple-projects", "{DAF4ADBB-250D-0A80-76AC-796D3C9CD4A9}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{986A884E-2D1F-75CC-48B5-B2716C96E4D3}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleApp.Data", "split-data-and-models-between-multiple-projects\src\SampleApp.Data\SampleApp.Data.csproj", "{6C744129-0A51-4110-93E4-FCD652680C21}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleApp.Models", "split-data-and-models-between-multiple-projects\src\SampleApp.Models\SampleApp.Models.csproj", "{E57FA06A-5CAA-4911-85C5-25A9F0C7E97C}"
+EndProject
+Project("{00D1A9C2-B5F0-4AF3-8072-F6C62B433612}") = "SampleApp.Sql", "split-data-and-models-between-multiple-projects\src\SampleApp.Sql\SampleApp.Sql.sqlproj", "{8F4BE58C-4C65-4960-9BD4-F785F1AD6EB1}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "build\_build.csproj", "{A9E02FAB-D5FA-4381-9BC9-F3BA8C9AF559}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {A9E02FAB-D5FA-4381-9BC9-F3BA8C9AF559}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A9E02FAB-D5FA-4381-9BC9-F3BA8C9AF559}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {50C548F6-BD90-44B2-939B-88E157BC1D77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {50C548F6-BD90-44B2-939B-88E157BC1D77}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {50C548F6-BD90-44B2-939B-88E157BC1D77}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {50C548F6-BD90-44B2-939B-88E157BC1D77}.Debug|x64.Build.0 = Debug|Any CPU
+ {50C548F6-BD90-44B2-939B-88E157BC1D77}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {50C548F6-BD90-44B2-939B-88E157BC1D77}.Debug|x86.Build.0 = Debug|Any CPU
+ {50C548F6-BD90-44B2-939B-88E157BC1D77}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {50C548F6-BD90-44B2-939B-88E157BC1D77}.Release|Any CPU.Build.0 = Release|Any CPU
+ {50C548F6-BD90-44B2-939B-88E157BC1D77}.Release|x64.ActiveCfg = Release|Any CPU
+ {50C548F6-BD90-44B2-939B-88E157BC1D77}.Release|x64.Build.0 = Release|Any CPU
+ {50C548F6-BD90-44B2-939B-88E157BC1D77}.Release|x86.ActiveCfg = Release|Any CPU
+ {50C548F6-BD90-44B2-939B-88E157BC1D77}.Release|x86.Build.0 = Release|Any CPU
+ {B6093DDC-14AF-4A21-989B-3AC63B89ACB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B6093DDC-14AF-4A21-989B-3AC63B89ACB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B6093DDC-14AF-4A21-989B-3AC63B89ACB0}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B6093DDC-14AF-4A21-989B-3AC63B89ACB0}.Debug|x64.Build.0 = Debug|Any CPU
+ {B6093DDC-14AF-4A21-989B-3AC63B89ACB0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {B6093DDC-14AF-4A21-989B-3AC63B89ACB0}.Debug|x86.Build.0 = Debug|Any CPU
+ {B6093DDC-14AF-4A21-989B-3AC63B89ACB0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B6093DDC-14AF-4A21-989B-3AC63B89ACB0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B6093DDC-14AF-4A21-989B-3AC63B89ACB0}.Release|x64.ActiveCfg = Release|Any CPU
+ {B6093DDC-14AF-4A21-989B-3AC63B89ACB0}.Release|x64.Build.0 = Release|Any CPU
+ {B6093DDC-14AF-4A21-989B-3AC63B89ACB0}.Release|x86.ActiveCfg = Release|Any CPU
+ {B6093DDC-14AF-4A21-989B-3AC63B89ACB0}.Release|x86.Build.0 = Release|Any CPU
+ {2809E8F4-B766-4D9D-B514-DEB85D974F5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2809E8F4-B766-4D9D-B514-DEB85D974F5C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2809E8F4-B766-4D9D-B514-DEB85D974F5C}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {2809E8F4-B766-4D9D-B514-DEB85D974F5C}.Debug|x64.Build.0 = Debug|Any CPU
+ {2809E8F4-B766-4D9D-B514-DEB85D974F5C}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {2809E8F4-B766-4D9D-B514-DEB85D974F5C}.Debug|x86.Build.0 = Debug|Any CPU
+ {2809E8F4-B766-4D9D-B514-DEB85D974F5C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2809E8F4-B766-4D9D-B514-DEB85D974F5C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2809E8F4-B766-4D9D-B514-DEB85D974F5C}.Release|x64.ActiveCfg = Release|Any CPU
+ {2809E8F4-B766-4D9D-B514-DEB85D974F5C}.Release|x64.Build.0 = Release|Any CPU
+ {2809E8F4-B766-4D9D-B514-DEB85D974F5C}.Release|x86.ActiveCfg = Release|Any CPU
+ {2809E8F4-B766-4D9D-B514-DEB85D974F5C}.Release|x86.Build.0 = Release|Any CPU
+ {1ADB10A5-ABA0-430F-88EB-10D2F2A379FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1ADB10A5-ABA0-430F-88EB-10D2F2A379FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1ADB10A5-ABA0-430F-88EB-10D2F2A379FC}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {1ADB10A5-ABA0-430F-88EB-10D2F2A379FC}.Debug|x64.Build.0 = Debug|Any CPU
+ {1ADB10A5-ABA0-430F-88EB-10D2F2A379FC}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {1ADB10A5-ABA0-430F-88EB-10D2F2A379FC}.Debug|x86.Build.0 = Debug|Any CPU
+ {1ADB10A5-ABA0-430F-88EB-10D2F2A379FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1ADB10A5-ABA0-430F-88EB-10D2F2A379FC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1ADB10A5-ABA0-430F-88EB-10D2F2A379FC}.Release|x64.ActiveCfg = Release|Any CPU
+ {1ADB10A5-ABA0-430F-88EB-10D2F2A379FC}.Release|x64.Build.0 = Release|Any CPU
+ {1ADB10A5-ABA0-430F-88EB-10D2F2A379FC}.Release|x86.ActiveCfg = Release|Any CPU
+ {1ADB10A5-ABA0-430F-88EB-10D2F2A379FC}.Release|x86.Build.0 = Release|Any CPU
+ {D0DE0C4D-8901-4FBD-A78C-B11D1B4675B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D0DE0C4D-8901-4FBD-A78C-B11D1B4675B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D0DE0C4D-8901-4FBD-A78C-B11D1B4675B4}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D0DE0C4D-8901-4FBD-A78C-B11D1B4675B4}.Debug|x64.Build.0 = Debug|Any CPU
+ {D0DE0C4D-8901-4FBD-A78C-B11D1B4675B4}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D0DE0C4D-8901-4FBD-A78C-B11D1B4675B4}.Debug|x86.Build.0 = Debug|Any CPU
+ {D0DE0C4D-8901-4FBD-A78C-B11D1B4675B4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D0DE0C4D-8901-4FBD-A78C-B11D1B4675B4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D0DE0C4D-8901-4FBD-A78C-B11D1B4675B4}.Release|x64.ActiveCfg = Release|Any CPU
+ {D0DE0C4D-8901-4FBD-A78C-B11D1B4675B4}.Release|x64.Build.0 = Release|Any CPU
+ {D0DE0C4D-8901-4FBD-A78C-B11D1B4675B4}.Release|x86.ActiveCfg = Release|Any CPU
+ {D0DE0C4D-8901-4FBD-A78C-B11D1B4675B4}.Release|x86.Build.0 = Release|Any CPU
+ {C7F9A6FC-67C8-4E44-B1CF-671A1315156D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C7F9A6FC-67C8-4E44-B1CF-671A1315156D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C7F9A6FC-67C8-4E44-B1CF-671A1315156D}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {C7F9A6FC-67C8-4E44-B1CF-671A1315156D}.Debug|x64.Build.0 = Debug|Any CPU
+ {C7F9A6FC-67C8-4E44-B1CF-671A1315156D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {C7F9A6FC-67C8-4E44-B1CF-671A1315156D}.Debug|x86.Build.0 = Debug|Any CPU
+ {C7F9A6FC-67C8-4E44-B1CF-671A1315156D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C7F9A6FC-67C8-4E44-B1CF-671A1315156D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C7F9A6FC-67C8-4E44-B1CF-671A1315156D}.Release|x64.ActiveCfg = Release|Any CPU
+ {C7F9A6FC-67C8-4E44-B1CF-671A1315156D}.Release|x64.Build.0 = Release|Any CPU
+ {C7F9A6FC-67C8-4E44-B1CF-671A1315156D}.Release|x86.ActiveCfg = Release|Any CPU
+ {C7F9A6FC-67C8-4E44-B1CF-671A1315156D}.Release|x86.Build.0 = Release|Any CPU
+ {F00C8951-341A-4738-A289-33504D2906D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F00C8951-341A-4738-A289-33504D2906D5}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {F00C8951-341A-4738-A289-33504D2906D5}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F00C8951-341A-4738-A289-33504D2906D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F00C8951-341A-4738-A289-33504D2906D5}.Release|x64.ActiveCfg = Release|Any CPU
+ {F00C8951-341A-4738-A289-33504D2906D5}.Release|x86.ActiveCfg = Release|Any CPU
+ {D098CDA1-D567-45E4-8C0E-53DFBA25EE22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D098CDA1-D567-45E4-8C0E-53DFBA25EE22}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D098CDA1-D567-45E4-8C0E-53DFBA25EE22}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D098CDA1-D567-45E4-8C0E-53DFBA25EE22}.Debug|x64.Build.0 = Debug|Any CPU
+ {D098CDA1-D567-45E4-8C0E-53DFBA25EE22}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D098CDA1-D567-45E4-8C0E-53DFBA25EE22}.Debug|x86.Build.0 = Debug|Any CPU
+ {D098CDA1-D567-45E4-8C0E-53DFBA25EE22}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D098CDA1-D567-45E4-8C0E-53DFBA25EE22}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D098CDA1-D567-45E4-8C0E-53DFBA25EE22}.Release|x64.ActiveCfg = Release|Any CPU
+ {D098CDA1-D567-45E4-8C0E-53DFBA25EE22}.Release|x64.Build.0 = Release|Any CPU
+ {D098CDA1-D567-45E4-8C0E-53DFBA25EE22}.Release|x86.ActiveCfg = Release|Any CPU
+ {D098CDA1-D567-45E4-8C0E-53DFBA25EE22}.Release|x86.Build.0 = Release|Any CPU
+ {E9BECDF9-5270-4E67-8B53-918DB5414427}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E9BECDF9-5270-4E67-8B53-918DB5414427}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E9BECDF9-5270-4E67-8B53-918DB5414427}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {E9BECDF9-5270-4E67-8B53-918DB5414427}.Debug|x64.Build.0 = Debug|Any CPU
+ {E9BECDF9-5270-4E67-8B53-918DB5414427}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {E9BECDF9-5270-4E67-8B53-918DB5414427}.Debug|x86.Build.0 = Debug|Any CPU
+ {E9BECDF9-5270-4E67-8B53-918DB5414427}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E9BECDF9-5270-4E67-8B53-918DB5414427}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E9BECDF9-5270-4E67-8B53-918DB5414427}.Release|x64.ActiveCfg = Release|Any CPU
+ {E9BECDF9-5270-4E67-8B53-918DB5414427}.Release|x64.Build.0 = Release|Any CPU
+ {E9BECDF9-5270-4E67-8B53-918DB5414427}.Release|x86.ActiveCfg = Release|Any CPU
+ {E9BECDF9-5270-4E67-8B53-918DB5414427}.Release|x86.Build.0 = Release|Any CPU
+ {FB8CDB1A-1DE0-488F-943A-115DE375344F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FB8CDB1A-1DE0-488F-943A-115DE375344F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FB8CDB1A-1DE0-488F-943A-115DE375344F}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FB8CDB1A-1DE0-488F-943A-115DE375344F}.Debug|x64.Build.0 = Debug|Any CPU
+ {FB8CDB1A-1DE0-488F-943A-115DE375344F}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FB8CDB1A-1DE0-488F-943A-115DE375344F}.Debug|x86.Build.0 = Debug|Any CPU
+ {FB8CDB1A-1DE0-488F-943A-115DE375344F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FB8CDB1A-1DE0-488F-943A-115DE375344F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FB8CDB1A-1DE0-488F-943A-115DE375344F}.Release|x64.ActiveCfg = Release|Any CPU
+ {FB8CDB1A-1DE0-488F-943A-115DE375344F}.Release|x64.Build.0 = Release|Any CPU
+ {FB8CDB1A-1DE0-488F-943A-115DE375344F}.Release|x86.ActiveCfg = Release|Any CPU
+ {FB8CDB1A-1DE0-488F-943A-115DE375344F}.Release|x86.Build.0 = Release|Any CPU
+ {0756435B-A795-4CC3-BA73-E2AB0F436F39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0756435B-A795-4CC3-BA73-E2AB0F436F39}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0756435B-A795-4CC3-BA73-E2AB0F436F39}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {0756435B-A795-4CC3-BA73-E2AB0F436F39}.Debug|x64.Build.0 = Debug|Any CPU
+ {0756435B-A795-4CC3-BA73-E2AB0F436F39}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {0756435B-A795-4CC3-BA73-E2AB0F436F39}.Debug|x86.Build.0 = Debug|Any CPU
+ {0756435B-A795-4CC3-BA73-E2AB0F436F39}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0756435B-A795-4CC3-BA73-E2AB0F436F39}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0756435B-A795-4CC3-BA73-E2AB0F436F39}.Release|x64.ActiveCfg = Release|Any CPU
+ {0756435B-A795-4CC3-BA73-E2AB0F436F39}.Release|x64.Build.0 = Release|Any CPU
+ {0756435B-A795-4CC3-BA73-E2AB0F436F39}.Release|x86.ActiveCfg = Release|Any CPU
+ {0756435B-A795-4CC3-BA73-E2AB0F436F39}.Release|x86.Build.0 = Release|Any CPU
+ {F03B61E0-1EB5-4ECB-8E43-1ED6A31E7665}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F03B61E0-1EB5-4ECB-8E43-1ED6A31E7665}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F03B61E0-1EB5-4ECB-8E43-1ED6A31E7665}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {F03B61E0-1EB5-4ECB-8E43-1ED6A31E7665}.Debug|x64.Build.0 = Debug|Any CPU
+ {F03B61E0-1EB5-4ECB-8E43-1ED6A31E7665}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F03B61E0-1EB5-4ECB-8E43-1ED6A31E7665}.Debug|x86.Build.0 = Debug|Any CPU
+ {F03B61E0-1EB5-4ECB-8E43-1ED6A31E7665}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F03B61E0-1EB5-4ECB-8E43-1ED6A31E7665}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F03B61E0-1EB5-4ECB-8E43-1ED6A31E7665}.Release|x64.ActiveCfg = Release|Any CPU
+ {F03B61E0-1EB5-4ECB-8E43-1ED6A31E7665}.Release|x64.Build.0 = Release|Any CPU
+ {F03B61E0-1EB5-4ECB-8E43-1ED6A31E7665}.Release|x86.ActiveCfg = Release|Any CPU
+ {F03B61E0-1EB5-4ECB-8E43-1ED6A31E7665}.Release|x86.Build.0 = Release|Any CPU
+ {DA0491F2-641D-4E6D-9B97-DC465C1CCE33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DA0491F2-641D-4E6D-9B97-DC465C1CCE33}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DA0491F2-641D-4E6D-9B97-DC465C1CCE33}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {DA0491F2-641D-4E6D-9B97-DC465C1CCE33}.Debug|x64.Build.0 = Debug|Any CPU
+ {DA0491F2-641D-4E6D-9B97-DC465C1CCE33}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {DA0491F2-641D-4E6D-9B97-DC465C1CCE33}.Debug|x86.Build.0 = Debug|Any CPU
+ {DA0491F2-641D-4E6D-9B97-DC465C1CCE33}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DA0491F2-641D-4E6D-9B97-DC465C1CCE33}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DA0491F2-641D-4E6D-9B97-DC465C1CCE33}.Release|x64.ActiveCfg = Release|Any CPU
+ {DA0491F2-641D-4E6D-9B97-DC465C1CCE33}.Release|x64.Build.0 = Release|Any CPU
+ {DA0491F2-641D-4E6D-9B97-DC465C1CCE33}.Release|x86.ActiveCfg = Release|Any CPU
+ {DA0491F2-641D-4E6D-9B97-DC465C1CCE33}.Release|x86.Build.0 = Release|Any CPU
+ {DF6874DC-C650-43B5-AB7E-55CA87F7C515}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DF6874DC-C650-43B5-AB7E-55CA87F7C515}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DF6874DC-C650-43B5-AB7E-55CA87F7C515}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {DF6874DC-C650-43B5-AB7E-55CA87F7C515}.Debug|x64.Build.0 = Debug|Any CPU
+ {DF6874DC-C650-43B5-AB7E-55CA87F7C515}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {DF6874DC-C650-43B5-AB7E-55CA87F7C515}.Debug|x86.Build.0 = Debug|Any CPU
+ {DF6874DC-C650-43B5-AB7E-55CA87F7C515}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DF6874DC-C650-43B5-AB7E-55CA87F7C515}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DF6874DC-C650-43B5-AB7E-55CA87F7C515}.Release|x64.ActiveCfg = Release|Any CPU
+ {DF6874DC-C650-43B5-AB7E-55CA87F7C515}.Release|x64.Build.0 = Release|Any CPU
+ {DF6874DC-C650-43B5-AB7E-55CA87F7C515}.Release|x86.ActiveCfg = Release|Any CPU
+ {DF6874DC-C650-43B5-AB7E-55CA87F7C515}.Release|x86.Build.0 = Release|Any CPU
+ {311609F6-420D-4B05-8E66-B1B084C45D19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {311609F6-420D-4B05-8E66-B1B084C45D19}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {311609F6-420D-4B05-8E66-B1B084C45D19}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {311609F6-420D-4B05-8E66-B1B084C45D19}.Debug|x64.Build.0 = Debug|Any CPU
+ {311609F6-420D-4B05-8E66-B1B084C45D19}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {311609F6-420D-4B05-8E66-B1B084C45D19}.Debug|x86.Build.0 = Debug|Any CPU
+ {311609F6-420D-4B05-8E66-B1B084C45D19}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {311609F6-420D-4B05-8E66-B1B084C45D19}.Release|Any CPU.Build.0 = Release|Any CPU
+ {311609F6-420D-4B05-8E66-B1B084C45D19}.Release|x64.ActiveCfg = Release|Any CPU
+ {311609F6-420D-4B05-8E66-B1B084C45D19}.Release|x64.Build.0 = Release|Any CPU
+ {311609F6-420D-4B05-8E66-B1B084C45D19}.Release|x86.ActiveCfg = Release|Any CPU
+ {311609F6-420D-4B05-8E66-B1B084C45D19}.Release|x86.Build.0 = Release|Any CPU
+ {433E6F74-5C51-43A5-A92C-C90D8DEB0D98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {433E6F74-5C51-43A5-A92C-C90D8DEB0D98}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {433E6F74-5C51-43A5-A92C-C90D8DEB0D98}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {433E6F74-5C51-43A5-A92C-C90D8DEB0D98}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {433E6F74-5C51-43A5-A92C-C90D8DEB0D98}.Release|x64.ActiveCfg = Release|Any CPU
+ {433E6F74-5C51-43A5-A92C-C90D8DEB0D98}.Release|x86.ActiveCfg = Release|Any CPU
+ {7973CB94-3824-48AD-816E-CD9EBF217B3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7973CB94-3824-48AD-816E-CD9EBF217B3A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7973CB94-3824-48AD-816E-CD9EBF217B3A}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {7973CB94-3824-48AD-816E-CD9EBF217B3A}.Debug|x64.Build.0 = Debug|Any CPU
+ {7973CB94-3824-48AD-816E-CD9EBF217B3A}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {7973CB94-3824-48AD-816E-CD9EBF217B3A}.Debug|x86.Build.0 = Debug|Any CPU
+ {7973CB94-3824-48AD-816E-CD9EBF217B3A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7973CB94-3824-48AD-816E-CD9EBF217B3A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7973CB94-3824-48AD-816E-CD9EBF217B3A}.Release|x64.ActiveCfg = Release|Any CPU
+ {7973CB94-3824-48AD-816E-CD9EBF217B3A}.Release|x64.Build.0 = Release|Any CPU
+ {7973CB94-3824-48AD-816E-CD9EBF217B3A}.Release|x86.ActiveCfg = Release|Any CPU
+ {7973CB94-3824-48AD-816E-CD9EBF217B3A}.Release|x86.Build.0 = Release|Any CPU
+ {E283EB20-A10D-482B-8320-93AFC70C36A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E283EB20-A10D-482B-8320-93AFC70C36A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E283EB20-A10D-482B-8320-93AFC70C36A8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {E283EB20-A10D-482B-8320-93AFC70C36A8}.Debug|x64.Build.0 = Debug|Any CPU
+ {E283EB20-A10D-482B-8320-93AFC70C36A8}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {E283EB20-A10D-482B-8320-93AFC70C36A8}.Debug|x86.Build.0 = Debug|Any CPU
+ {E283EB20-A10D-482B-8320-93AFC70C36A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E283EB20-A10D-482B-8320-93AFC70C36A8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E283EB20-A10D-482B-8320-93AFC70C36A8}.Release|x64.ActiveCfg = Release|Any CPU
+ {E283EB20-A10D-482B-8320-93AFC70C36A8}.Release|x64.Build.0 = Release|Any CPU
+ {E283EB20-A10D-482B-8320-93AFC70C36A8}.Release|x86.ActiveCfg = Release|Any CPU
+ {E283EB20-A10D-482B-8320-93AFC70C36A8}.Release|x86.Build.0 = Release|Any CPU
+ {C4A32153-A694-401F-B54A-38F7642D24D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C4A32153-A694-401F-B54A-38F7642D24D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C4A32153-A694-401F-B54A-38F7642D24D9}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {C4A32153-A694-401F-B54A-38F7642D24D9}.Debug|x64.Build.0 = Debug|Any CPU
+ {C4A32153-A694-401F-B54A-38F7642D24D9}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {C4A32153-A694-401F-B54A-38F7642D24D9}.Debug|x86.Build.0 = Debug|Any CPU
+ {C4A32153-A694-401F-B54A-38F7642D24D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C4A32153-A694-401F-B54A-38F7642D24D9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C4A32153-A694-401F-B54A-38F7642D24D9}.Release|x64.ActiveCfg = Release|Any CPU
+ {C4A32153-A694-401F-B54A-38F7642D24D9}.Release|x64.Build.0 = Release|Any CPU
+ {C4A32153-A694-401F-B54A-38F7642D24D9}.Release|x86.ActiveCfg = Release|Any CPU
+ {C4A32153-A694-401F-B54A-38F7642D24D9}.Release|x86.Build.0 = Release|Any CPU
+ {9F527768-04B3-4DED-89B7-0D0A8DA59DB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9F527768-04B3-4DED-89B7-0D0A8DA59DB9}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {9F527768-04B3-4DED-89B7-0D0A8DA59DB9}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {9F527768-04B3-4DED-89B7-0D0A8DA59DB9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9F527768-04B3-4DED-89B7-0D0A8DA59DB9}.Release|x64.ActiveCfg = Release|Any CPU
+ {9F527768-04B3-4DED-89B7-0D0A8DA59DB9}.Release|x86.ActiveCfg = Release|Any CPU
+ {E8265A69-7C88-4728-ACD2-710A5F7C0E3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E8265A69-7C88-4728-ACD2-710A5F7C0E3A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E8265A69-7C88-4728-ACD2-710A5F7C0E3A}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {E8265A69-7C88-4728-ACD2-710A5F7C0E3A}.Debug|x64.Build.0 = Debug|Any CPU
+ {E8265A69-7C88-4728-ACD2-710A5F7C0E3A}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {E8265A69-7C88-4728-ACD2-710A5F7C0E3A}.Debug|x86.Build.0 = Debug|Any CPU
+ {E8265A69-7C88-4728-ACD2-710A5F7C0E3A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E8265A69-7C88-4728-ACD2-710A5F7C0E3A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E8265A69-7C88-4728-ACD2-710A5F7C0E3A}.Release|x64.ActiveCfg = Release|Any CPU
+ {E8265A69-7C88-4728-ACD2-710A5F7C0E3A}.Release|x64.Build.0 = Release|Any CPU
+ {E8265A69-7C88-4728-ACD2-710A5F7C0E3A}.Release|x86.ActiveCfg = Release|Any CPU
+ {E8265A69-7C88-4728-ACD2-710A5F7C0E3A}.Release|x86.Build.0 = Release|Any CPU
+ {1B282238-83D7-4FBD-BE3C-180A82253543}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1B282238-83D7-4FBD-BE3C-180A82253543}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1B282238-83D7-4FBD-BE3C-180A82253543}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {1B282238-83D7-4FBD-BE3C-180A82253543}.Debug|x64.Build.0 = Debug|Any CPU
+ {1B282238-83D7-4FBD-BE3C-180A82253543}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {1B282238-83D7-4FBD-BE3C-180A82253543}.Debug|x86.Build.0 = Debug|Any CPU
+ {1B282238-83D7-4FBD-BE3C-180A82253543}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1B282238-83D7-4FBD-BE3C-180A82253543}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1B282238-83D7-4FBD-BE3C-180A82253543}.Release|x64.ActiveCfg = Release|Any CPU
+ {1B282238-83D7-4FBD-BE3C-180A82253543}.Release|x64.Build.0 = Release|Any CPU
+ {1B282238-83D7-4FBD-BE3C-180A82253543}.Release|x86.ActiveCfg = Release|Any CPU
+ {1B282238-83D7-4FBD-BE3C-180A82253543}.Release|x86.Build.0 = Release|Any CPU
+ {6C744129-0A51-4110-93E4-FCD652680C21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6C744129-0A51-4110-93E4-FCD652680C21}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6C744129-0A51-4110-93E4-FCD652680C21}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {6C744129-0A51-4110-93E4-FCD652680C21}.Debug|x64.Build.0 = Debug|Any CPU
+ {6C744129-0A51-4110-93E4-FCD652680C21}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {6C744129-0A51-4110-93E4-FCD652680C21}.Debug|x86.Build.0 = Debug|Any CPU
+ {6C744129-0A51-4110-93E4-FCD652680C21}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6C744129-0A51-4110-93E4-FCD652680C21}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6C744129-0A51-4110-93E4-FCD652680C21}.Release|x64.ActiveCfg = Release|Any CPU
+ {6C744129-0A51-4110-93E4-FCD652680C21}.Release|x64.Build.0 = Release|Any CPU
+ {6C744129-0A51-4110-93E4-FCD652680C21}.Release|x86.ActiveCfg = Release|Any CPU
+ {6C744129-0A51-4110-93E4-FCD652680C21}.Release|x86.Build.0 = Release|Any CPU
+ {E57FA06A-5CAA-4911-85C5-25A9F0C7E97C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E57FA06A-5CAA-4911-85C5-25A9F0C7E97C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E57FA06A-5CAA-4911-85C5-25A9F0C7E97C}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {E57FA06A-5CAA-4911-85C5-25A9F0C7E97C}.Debug|x64.Build.0 = Debug|Any CPU
+ {E57FA06A-5CAA-4911-85C5-25A9F0C7E97C}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {E57FA06A-5CAA-4911-85C5-25A9F0C7E97C}.Debug|x86.Build.0 = Debug|Any CPU
+ {E57FA06A-5CAA-4911-85C5-25A9F0C7E97C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E57FA06A-5CAA-4911-85C5-25A9F0C7E97C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E57FA06A-5CAA-4911-85C5-25A9F0C7E97C}.Release|x64.ActiveCfg = Release|Any CPU
+ {E57FA06A-5CAA-4911-85C5-25A9F0C7E97C}.Release|x64.Build.0 = Release|Any CPU
+ {E57FA06A-5CAA-4911-85C5-25A9F0C7E97C}.Release|x86.ActiveCfg = Release|Any CPU
+ {E57FA06A-5CAA-4911-85C5-25A9F0C7E97C}.Release|x86.Build.0 = Release|Any CPU
+ {8F4BE58C-4C65-4960-9BD4-F785F1AD6EB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8F4BE58C-4C65-4960-9BD4-F785F1AD6EB1}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {8F4BE58C-4C65-4960-9BD4-F785F1AD6EB1}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {8F4BE58C-4C65-4960-9BD4-F785F1AD6EB1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8F4BE58C-4C65-4960-9BD4-F785F1AD6EB1}.Release|x64.ActiveCfg = Release|Any CPU
+ {8F4BE58C-4C65-4960-9BD4-F785F1AD6EB1}.Release|x86.ActiveCfg = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {50C548F6-BD90-44B2-939B-88E157BC1D77} = {1F87798A-3DA2-1D52-37E6-92287F21560B}
+ {B6093DDC-14AF-4A21-989B-3AC63B89ACB0} = {1F87798A-3DA2-1D52-37E6-92287F21560B}
+ {2809E8F4-B766-4D9D-B514-DEB85D974F5C} = {8FE76333-615D-4D0B-08EF-9ACA145B22E5}
+ {1ADB10A5-ABA0-430F-88EB-10D2F2A379FC} = {8FE76333-615D-4D0B-08EF-9ACA145B22E5}
+ {D0DE0C4D-8901-4FBD-A78C-B11D1B4675B4} = {F300D630-7571-566C-DE3A-0237458CBD19}
+ {C7F9A6FC-67C8-4E44-B1CF-671A1315156D} = {10305151-72DA-BBBB-C817-BD890FA250F2}
+ {F00C8951-341A-4738-A289-33504D2906D5} = {10305151-72DA-BBBB-C817-BD890FA250F2}
+ {D098CDA1-D567-45E4-8C0E-53DFBA25EE22} = {CA0ABCE0-AAC8-D42B-D483-0AD6CB9ED44A}
+ {E9BECDF9-5270-4E67-8B53-918DB5414427} = {46A6B6E4-1F62-AC21-FF7F-BCB260772A08}
+ {FB8CDB1A-1DE0-488F-943A-115DE375344F} = {46A6B6E4-1F62-AC21-FF7F-BCB260772A08}
+ {0756435B-A795-4CC3-BA73-E2AB0F436F39} = {D19774F8-5390-DECA-0D5D-DB3D3B1934CC}
+ {F03B61E0-1EB5-4ECB-8E43-1ED6A31E7665} = {D19774F8-5390-DECA-0D5D-DB3D3B1934CC}
+ {DA0491F2-641D-4E6D-9B97-DC465C1CCE33} = {0FBFF59C-0FC2-5776-A3F6-C46E2EF347EC}
+ {DF6874DC-C650-43B5-AB7E-55CA87F7C515} = {0FBFF59C-0FC2-5776-A3F6-C46E2EF347EC}
+ {311609F6-420D-4B05-8E66-B1B084C45D19} = {EBF3C506-8F29-9654-7600-23BD3F25C924}
+ {433E6F74-5C51-43A5-A92C-C90D8DEB0D98} = {EBF3C506-8F29-9654-7600-23BD3F25C924}
+ {7973CB94-3824-48AD-816E-CD9EBF217B3A} = {1B681BF4-A602-D408-2E69-2B57B87575B2}
+ {E283EB20-A10D-482B-8320-93AFC70C36A8} = {1B681BF4-A602-D408-2E69-2B57B87575B2}
+ {C4A32153-A694-401F-B54A-38F7642D24D9} = {533FC926-FE64-7363-FF68-925D042523EE}
+ {9F527768-04B3-4DED-89B7-0D0A8DA59DB9} = {533FC926-FE64-7363-FF68-925D042523EE}
+ {E8265A69-7C88-4728-ACD2-710A5F7C0E3A} = {992222C4-ADE0-6BF1-7230-A9C65755AE09}
+ {1B282238-83D7-4FBD-BE3C-180A82253543} = {992222C4-ADE0-6BF1-7230-A9C65755AE09}
+ {986A884E-2D1F-75CC-48B5-B2716C96E4D3} = {DAF4ADBB-250D-0A80-76AC-796D3C9CD4A9}
+ {6C744129-0A51-4110-93E4-FCD652680C21} = {986A884E-2D1F-75CC-48B5-B2716C96E4D3}
+ {E57FA06A-5CAA-4911-85C5-25A9F0C7E97C} = {986A884E-2D1F-75CC-48B5-B2716C96E4D3}
+ {8F4BE58C-4C65-4960-9BD4-F785F1AD6EB1} = {986A884E-2D1F-75CC-48B5-B2716C96E4D3}
+ EndGlobalSection
+EndGlobal
diff --git a/samples/build.cmd b/samples/build.cmd
new file mode 100644
index 0000000..b08cc59
--- /dev/null
+++ b/samples/build.cmd
@@ -0,0 +1,7 @@
+:; set -eo pipefail
+:; SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
+:; ${SCRIPT_DIR}/build.sh "$@"
+:; exit $?
+
+@ECHO OFF
+powershell -ExecutionPolicy ByPass -NoProfile -File "%~dp0build.ps1" %*
diff --git a/samples/build.ps1 b/samples/build.ps1
new file mode 100644
index 0000000..e76a5b2
--- /dev/null
+++ b/samples/build.ps1
@@ -0,0 +1,106 @@
+#!/usr/bin/env pwsh
+<#
+.SYNOPSIS
+ Build script for samples solution with proper dependency management
+.DESCRIPTION
+ This script ensures the main JD.Efcpt.Build packages are built first,
+ then builds the samples solution.
+.PARAMETER Configuration
+ Build configuration (Debug or Release). Default is Debug.
+.PARAMETER SkipMainBuild
+ Skip building the main solution packages
+#>
+
+param(
+ [ValidateSet('Debug', 'Release')]
+ [string]$Configuration = 'Debug',
+ [switch]$SkipMainBuild
+)
+
+$ErrorActionPreference = 'Stop'
+Set-StrictMode -Version Latest
+
+$samplesRoot = $PSScriptRoot
+$repoRoot = Split-Path $samplesRoot -Parent
+$mainSolution = Join-Path $repoRoot "JD.Efcpt.Build.sln"
+$packagesDir = Join-Path $repoRoot "packages"
+$samplesSolution = Join-Path $samplesRoot "Samples.sln"
+
+Write-Host "========================================" -ForegroundColor Cyan
+Write-Host "JD.Efcpt.Build Samples Build Script" -ForegroundColor Cyan
+Write-Host "========================================" -ForegroundColor Cyan
+Write-Host ""
+
+# Step 1: Build main solution packages
+if (-not $SkipMainBuild) {
+ Write-Host "Step 1: Building main solution..." -ForegroundColor Yellow
+ Push-Location $repoRoot
+ try {
+ dotnet build $mainSolution --configuration $Configuration
+ if ($LASTEXITCODE -ne 0) {
+ throw "Failed to build main solution"
+ }
+ Write-Host "✓ Main solution built successfully" -ForegroundColor Green
+ Write-Host ""
+
+ Write-Host "Step 2: Packing main solution..." -ForegroundColor Yellow
+ dotnet pack $mainSolution --configuration $Configuration --output $packagesDir --no-build
+ if ($LASTEXITCODE -ne 0) {
+ throw "Failed to pack main solution"
+ }
+ Write-Host "✓ Main solution packed successfully" -ForegroundColor Green
+ Write-Host ""
+
+ Write-Host "Step 3: Fixing sample project issues..." -ForegroundColor Yellow
+ & "$samplesRoot\fix-samples.ps1" -Quiet
+ Write-Host " ✓ Sample fixes applied" -ForegroundColor Green
+ Write-Host ""
+ }
+ finally {
+ Pop-Location
+ }
+}
+else {
+ Write-Host "Skipping main solution build" -ForegroundColor Gray
+ Write-Host ""
+}
+
+# Step 2: Restore and build samples solution
+Write-Host "Step 4: Restoring sample solution..." -ForegroundColor Yellow
+Write-Host "Note: Using NuGet.config for package sources (local packages + nuget.org)" -ForegroundColor Gray
+dotnet restore $samplesSolution
+$restoreExitCode = $LASTEXITCODE
+
+if ($restoreExitCode -ne 0) {
+ Write-Host "⚠ Restore completed with errors" -ForegroundColor Yellow
+ Write-Host ""
+ Write-Host "Known issues:" -ForegroundColor Yellow
+ Write-Host " - sdk-zero-config: Requires SDK version in global.json" -ForegroundColor Gray
+ Write-Host " - Some samples: Target framework may not match EF Core package version" -ForegroundColor Gray
+ Write-Host ""
+}
+else {
+ Write-Host "✓ Sample solution restored" -ForegroundColor Green
+ Write-Host ""
+}
+
+Write-Host "Step 5: Building sample solution..." -ForegroundColor Yellow
+dotnet build $samplesSolution --configuration $Configuration --no-restore
+$buildExitCode = $LASTEXITCODE
+
+if ($buildExitCode -ne 0) {
+ Write-Host "⚠ Build completed with errors" -ForegroundColor Yellow
+ Write-Host ""
+ Write-Host "Some samples may have pre-existing issues." -ForegroundColor Gray
+ Write-Host "Check individual sample README files for requirements." -ForegroundColor Gray
+ Write-Host ""
+ exit 1
+}
+else {
+ Write-Host "✓ Sample solution built successfully" -ForegroundColor Green
+ Write-Host ""
+}
+
+Write-Host "========================================" -ForegroundColor Cyan
+Write-Host "Build completed! 🎉" -ForegroundColor Green
+Write-Host "========================================" -ForegroundColor Cyan
diff --git a/samples/build.sh b/samples/build.sh
new file mode 100644
index 0000000..fdff0c6
--- /dev/null
+++ b/samples/build.sh
@@ -0,0 +1,67 @@
+#!/usr/bin/env bash
+
+bash --version 2>&1 | head -n 1
+
+set -eo pipefail
+SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
+
+###########################################################################
+# CONFIGURATION
+###########################################################################
+
+BUILD_PROJECT_FILE="$SCRIPT_DIR/build/_build.csproj"
+TEMP_DIRECTORY="$SCRIPT_DIR//.nuke/temp"
+
+DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json"
+DOTNET_INSTALL_URL="https://dot.net/v1/dotnet-install.sh"
+DOTNET_CHANNEL="STS"
+
+export DOTNET_CLI_TELEMETRY_OPTOUT=1
+export DOTNET_NOLOGO=1
+
+###########################################################################
+# EXECUTION
+###########################################################################
+
+function FirstJsonValue {
+ perl -nle 'print $1 if m{"'"$1"'": "([^"]+)",?}' <<< "${@:2}"
+}
+
+# If dotnet CLI is installed globally and it matches requested version, use for execution
+if [ -x "$(command -v dotnet)" ] && dotnet --version &>/dev/null; then
+ export DOTNET_EXE="$(command -v dotnet)"
+else
+ # Download install script
+ DOTNET_INSTALL_FILE="$TEMP_DIRECTORY/dotnet-install.sh"
+ mkdir -p "$TEMP_DIRECTORY"
+ curl -Lsfo "$DOTNET_INSTALL_FILE" "$DOTNET_INSTALL_URL"
+ chmod +x "$DOTNET_INSTALL_FILE"
+
+ # If global.json exists, load expected version
+ if [[ -f "$DOTNET_GLOBAL_FILE" ]]; then
+ DOTNET_VERSION=$(FirstJsonValue "version" "$(cat "$DOTNET_GLOBAL_FILE")")
+ if [[ "$DOTNET_VERSION" == "" ]]; then
+ unset DOTNET_VERSION
+ fi
+ fi
+
+ # Install by channel or version
+ DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix"
+ if [[ -z ${DOTNET_VERSION+x} ]]; then
+ "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --channel "$DOTNET_CHANNEL" --no-path
+ else
+ "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --version "$DOTNET_VERSION" --no-path
+ fi
+ export DOTNET_EXE="$DOTNET_DIRECTORY/dotnet"
+ export PATH="$DOTNET_DIRECTORY:$PATH"
+fi
+
+echo "Microsoft (R) .NET SDK version $("$DOTNET_EXE" --version)"
+
+if [[ ! -z ${NUKE_ENTERPRISE_TOKEN+x} && "$NUKE_ENTERPRISE_TOKEN" != "" ]]; then
+ "$DOTNET_EXE" nuget remove source "nuke-enterprise" &>/dev/null || true
+ "$DOTNET_EXE" nuget add source "https://f.feedz.io/nuke/enterprise/nuget" --name "nuke-enterprise" --username "PAT" --password "$NUKE_ENTERPRISE_TOKEN" --store-password-in-clear-text &>/dev/null || true
+fi
+
+"$DOTNET_EXE" build "$BUILD_PROJECT_FILE" /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet
+"$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" --no-build -- "$@"
diff --git a/src/JD.Efcpt.Build.Definitions/BuildPropsFactory.cs b/src/JD.Efcpt.Build.Definitions/BuildPropsFactory.cs
new file mode 100644
index 0000000..862ec84
--- /dev/null
+++ b/src/JD.Efcpt.Build.Definitions/BuildPropsFactory.cs
@@ -0,0 +1,30 @@
+using JD.MSBuild.Fluent;
+using JD.MSBuild.Fluent.Fluent;
+using JD.MSBuild.Fluent.Typed;
+
+namespace JD.Efcpt.Build.Definitions;
+
+///
+/// MSBuild package definition scaffolded from JD.Efcpt.Build.xml
+///
+public static class BuildPropsFactory
+{
+ public static PackageDefinition Create()
+ {
+ return Package.Define("JD.Efcpt.Build")
+ .Props(p =>
+ {
+ p.Property("true");
+ p.Import("..\\buildTransitive\\JD.Efcpt.Build.props");
+ })
+ .Build();
+ }
+
+ // Strongly-typed property names
+ public readonly struct EfcptIsDirectReference : IMsBuildPropertyName
+ {
+ public string Name => "_EfcptIsDirectReference";
+ }
+}
+
+
diff --git a/src/JD.Efcpt.Build.Definitions/BuildTargetsFactory.cs b/src/JD.Efcpt.Build.Definitions/BuildTargetsFactory.cs
new file mode 100644
index 0000000..cf96247
--- /dev/null
+++ b/src/JD.Efcpt.Build.Definitions/BuildTargetsFactory.cs
@@ -0,0 +1,20 @@
+using JD.MSBuild.Fluent;
+using JD.MSBuild.Fluent.Fluent;
+
+namespace JD.Efcpt.Build.Definitions;
+
+///
+/// MSBuild package definition scaffolded from JD.Efcpt.Build.xml
+///
+public static class BuildTargetsFactory
+{
+ public static PackageDefinition Create()
+ {
+ return Package.Define("JD.Efcpt.Build")
+ .Targets(t =>
+ {
+ t.Import("..\\buildTransitive\\JD.Efcpt.Build.targets");
+ })
+ .Build();
+ }
+}
diff --git a/src/JD.Efcpt.Build.Definitions/BuildTransitivePropsFactory.cs b/src/JD.Efcpt.Build.Definitions/BuildTransitivePropsFactory.cs
new file mode 100644
index 0000000..6674c39
--- /dev/null
+++ b/src/JD.Efcpt.Build.Definitions/BuildTransitivePropsFactory.cs
@@ -0,0 +1,556 @@
+using JD.MSBuild.Fluent;
+using JD.MSBuild.Fluent.Fluent;
+using JD.MSBuild.Fluent.Typed;
+
+namespace JD.Efcpt.Build.Definitions;
+
+///
+/// MSBuild package definition scaffolded from JD.Efcpt.Build.xml
+///
+public static class BuildTransitivePropsFactory
+{
+ public static PackageDefinition Create()
+ {
+ return Package.Define("JD.Efcpt.Build")
+ .Props(p =>
+ {
+ p.PropertyGroup(null, group =>
+ {
+ group.Property( "true", "'$(EfcptEnabled)'==''");
+ group.Property( "$(BaseIntermediateOutputPath)efcpt\\", "'$(EfcptOutput)'==''");
+ group.Property( "$(EfcptOutput)Generated\\", "'$(EfcptGeneratedDir)'==''");
+ group.Property( "", "'$(EfcptSqlProj)'==''");
+ group.Property( "", "'$(EfcptDacpac)'==''");
+ group.Property( "efcpt-config.json", "'$(EfcptConfig)'==''");
+ group.Property( "efcpt.renaming.json", "'$(EfcptRenaming)'==''");
+ group.Property( "Template", "'$(EfcptTemplateDir)'==''");
+ group.Property( "", "'$(EfcptConnectionString)'==''");
+ group.Property( "", "'$(EfcptAppSettings)'==''");
+ group.Property( "", "'$(EfcptAppConfig)'==''");
+ group.Property( "DefaultConnection", "'$(EfcptConnectionStringName)'==''");
+ group.Property( "mssql", "'$(EfcptProvider)'==''");
+ group.Property( "$(SolutionDir)", "'$(EfcptSolutionDir)'==''");
+ group.Property( "$(SolutionPath)", "'$(EfcptSolutionPath)'==''");
+ group.Property( "true", "'$(EfcptProbeSolutionDir)'==''");
+ group.Property( "auto", "'$(EfcptToolMode)'==''");
+ group.Property( "ErikEJ.EFCorePowerTools.Cli", "'$(EfcptToolPackageId)'==''");
+ group.Property( "10.*", "'$(EfcptToolVersion)'==''");
+ group.Property( "true", "'$(EfcptToolRestore)'==''");
+ group.Property( "efcpt", "'$(EfcptToolCommand)'==''");
+ group.Property( "", "'$(EfcptToolPath)'==''");
+ group.Property( "dotnet", "'$(EfcptDotNetExe)'==''");
+ group.Property( "$(EfcptOutput)fingerprint.txt", "'$(EfcptFingerprintFile)'==''");
+ group.Property( "$(EfcptOutput).efcpt.stamp", "'$(EfcptStampFile)'==''");
+ group.Property( "false", "'$(EfcptDetectGeneratedFileChanges)'==''");
+ group.Property( "minimal", "'$(EfcptLogVerbosity)'==''");
+ group.Property( "false", "'$(EfcptDumpResolvedInputs)'==''");
+ group.Property( "Info", "'$(EfcptAutoDetectWarningLevel)'==''");
+ group.Property( "Warn", "'$(EfcptSdkVersionWarningLevel)'==''");
+ group.Property( "false", "'$(EfcptCheckForUpdates)'==''");
+ group.Property( "24", "'$(EfcptUpdateCheckCacheHours)'==''");
+ group.Property( "false", "'$(EfcptForceUpdateCheck)'==''");
+ group.Property( "false", "'$(EfcptSplitOutputs)'==''");
+ group.Property( "", "'$(EfcptDataProject)'==''");
+ group.Property( "obj\\efcpt\\Generated\\", "'$(EfcptDataProjectOutputSubdir)'==''");
+ group.Property( "", "'$(EfcptExternalDataDir)'==''");
+ group.Property( "true", "'$(EfcptApplyMsBuildOverrides)'==''");
+ group.Property( "$(RootNamespace)", "'$(EfcptConfigRootNamespace)'=='' and '$(RootNamespace)'!=''");
+ group.Property( "$(MSBuildProjectName)", "'$(EfcptConfigRootNamespace)'==''");
+ group.Property( "", "'$(EfcptConfigDbContextName)'==''");
+ group.Property( "", "'$(EfcptConfigDbContextNamespace)'==''");
+ group.Property( "", "'$(EfcptConfigModelNamespace)'==''");
+ group.Property( "", "'$(EfcptConfigOutputPath)'==''");
+ group.Property( "", "'$(EfcptConfigDbContextOutputPath)'==''");
+ group.Property( "", "'$(EfcptConfigSplitDbContext)'==''");
+ group.Property( "", "'$(EfcptConfigUseSchemaFolders)'==''");
+ group.Property( "", "'$(EfcptConfigUseSchemaNamespaces)'==''");
+ group.Property( "", "'$(EfcptConfigEnableOnConfiguring)'==''");
+ group.Property( "", "'$(EfcptConfigGenerationType)'==''");
+ group.Property( "", "'$(EfcptConfigUseDatabaseNames)'==''");
+ group.Property( "", "'$(EfcptConfigUseDataAnnotations)'==''");
+ group.Property( "", "'$(EfcptConfigUseInflector)'==''");
+ group.Property( "", "'$(EfcptConfigUseLegacyInflector)'==''");
+ group.Property( "", "'$(EfcptConfigUseManyToManyEntity)'==''");
+ group.Property( "", "'$(EfcptConfigUseT4)'==''");
+ group.Property( "", "'$(EfcptConfigUseT4Split)'==''");
+ group.Property( "", "'$(EfcptConfigRemoveDefaultSqlFromBool)'==''");
+ group.Property( "", "'$(EfcptConfigSoftDeleteObsoleteFiles)'==''");
+ group.Property( "", "'$(EfcptConfigDiscoverMultipleResultSets)'==''");
+ group.Property( "", "'$(EfcptConfigUseAlternateResultSetDiscovery)'==''");
+ group.Property( "", "'$(EfcptConfigT4TemplatePath)'==''");
+ group.Property( "", "'$(EfcptConfigUseNoNavigations)'==''");
+ group.Property( "", "'$(EfcptConfigMergeDacpacs)'==''");
+ group.Property( "", "'$(EfcptConfigRefreshObjectLists)'==''");
+ group.Property( "", "'$(EfcptConfigGenerateMermaidDiagram)'==''");
+ group.Property( "", "'$(EfcptConfigUseDecimalAnnotationForSprocs)'==''");
+ group.Property( "", "'$(EfcptConfigUsePrefixNavigationNaming)'==''");
+ group.Property( "", "'$(EfcptConfigUseDatabaseNamesForRoutines)'==''");
+ group.Property( "", "'$(EfcptConfigUseInternalAccessForRoutines)'==''");
+ group.Property( "", "'$(EfcptConfigUseDateOnlyTimeOnly)'==''");
+ group.Property( "", "'$(EfcptConfigUseHierarchyId)'==''");
+ group.Property( "", "'$(EfcptConfigUseSpatial)'==''");
+ group.Property( "", "'$(EfcptConfigUseNodaTime)'==''");
+ group.Property( "", "'$(EfcptConfigPreserveCasingWithRegex)'==''");
+ group.Property( "false", "'$(EfcptEnableProfiling)'==''");
+ group.Property( "$(EfcptOutput)build-profile.json", "'$(EfcptProfilingOutput)'==''");
+ group.Property( "minimal", "'$(EfcptProfilingVerbosity)'==''");
+ });
+ p.PropertyGroup(null, group =>
+ {
+ group.Property( "microsoft-build-sql", "'$(EfcptSqlProjType)'==''");
+ group.Property( "csharp", "'$(EfcptSqlProjLanguage)'==''");
+ group.Property( "$(MSBuildProjectDirectory)\\", "'$(EfcptSqlProjOutputDir)'==''");
+ group.Property( "$(MSBuildProjectDirectory)\\", "'$(EfcptSqlScriptsDir)'==''");
+ group.Property( "Sql160", "'$(EfcptSqlServerVersion)'==''");
+ group.Property( "", "'$(EfcptSqlPackageToolVersion)'==''");
+ group.Property( "true", "'$(EfcptSqlPackageToolRestore)'==''");
+ group.Property( "", "'$(EfcptSqlPackageToolPath)'==''");
+ });
+ })
+ .Targets(t =>
+ {
+ t.PropertyGroup(null, group =>
+ {
+ group.Property( "true", "'$(EfcptEnabled)'==''");
+ group.Property( "$(BaseIntermediateOutputPath)efcpt\\", "'$(EfcptOutput)'==''");
+ group.Property( "$(EfcptOutput)Generated\\", "'$(EfcptGeneratedDir)'==''");
+ group.Property( "", "'$(EfcptSqlProj)'==''");
+ group.Property( "", "'$(EfcptDacpac)'==''");
+ group.Property( "efcpt-config.json", "'$(EfcptConfig)'==''");
+ group.Property( "efcpt.renaming.json", "'$(EfcptRenaming)'==''");
+ group.Property( "Template", "'$(EfcptTemplateDir)'==''");
+ group.Property( "", "'$(EfcptConnectionString)'==''");
+ group.Property( "", "'$(EfcptAppSettings)'==''");
+ group.Property( "", "'$(EfcptAppConfig)'==''");
+ group.Property( "DefaultConnection", "'$(EfcptConnectionStringName)'==''");
+ group.Property( "mssql", "'$(EfcptProvider)'==''");
+ group.Property( "$(SolutionDir)", "'$(EfcptSolutionDir)'==''");
+ group.Property( "$(SolutionPath)", "'$(EfcptSolutionPath)'==''");
+ group.Property( "true", "'$(EfcptProbeSolutionDir)'==''");
+ group.Property( "auto", "'$(EfcptToolMode)'==''");
+ group.Property( "ErikEJ.EFCorePowerTools.Cli", "'$(EfcptToolPackageId)'==''");
+ group.Property( "10.*", "'$(EfcptToolVersion)'==''");
+ group.Property( "true", "'$(EfcptToolRestore)'==''");
+ group.Property( "efcpt", "'$(EfcptToolCommand)'==''");
+ group.Property( "", "'$(EfcptToolPath)'==''");
+ group.Property( "dotnet", "'$(EfcptDotNetExe)'==''");
+ group.Property( "$(EfcptOutput)fingerprint.txt", "'$(EfcptFingerprintFile)'==''");
+ group.Property( "$(EfcptOutput).efcpt.stamp", "'$(EfcptStampFile)'==''");
+ group.Property( "false", "'$(EfcptDetectGeneratedFileChanges)'==''");
+ group.Property( "minimal", "'$(EfcptLogVerbosity)'==''");
+ group.Property( "false", "'$(EfcptDumpResolvedInputs)'==''");
+ group.Property( "Info", "'$(EfcptAutoDetectWarningLevel)'==''");
+ group.Property( "Warn", "'$(EfcptSdkVersionWarningLevel)'==''");
+ group.Property( "false", "'$(EfcptCheckForUpdates)'==''");
+ group.Property( "24", "'$(EfcptUpdateCheckCacheHours)'==''");
+ group.Property( "false", "'$(EfcptForceUpdateCheck)'==''");
+ group.Property( "false", "'$(EfcptSplitOutputs)'==''");
+ group.Property( "", "'$(EfcptDataProject)'==''");
+ group.Property( "obj\\efcpt\\Generated\\", "'$(EfcptDataProjectOutputSubdir)'==''");
+ group.Property( "", "'$(EfcptExternalDataDir)'==''");
+ group.Property( "true", "'$(EfcptApplyMsBuildOverrides)'==''");
+ group.Property( "$(RootNamespace)", "'$(EfcptConfigRootNamespace)'=='' and '$(RootNamespace)'!=''");
+ group.Property( "$(MSBuildProjectName)", "'$(EfcptConfigRootNamespace)'==''");
+ group.Property( "", "'$(EfcptConfigDbContextName)'==''");
+ group.Property( "", "'$(EfcptConfigDbContextNamespace)'==''");
+ group.Property( "", "'$(EfcptConfigModelNamespace)'==''");
+ group.Property( "", "'$(EfcptConfigOutputPath)'==''");
+ group.Property( "", "'$(EfcptConfigDbContextOutputPath)'==''");
+ group.Property( "", "'$(EfcptConfigSplitDbContext)'==''");
+ group.Property( "", "'$(EfcptConfigUseSchemaFolders)'==''");
+ group.Property( "", "'$(EfcptConfigUseSchemaNamespaces)'==''");
+ group.Property( "", "'$(EfcptConfigEnableOnConfiguring)'==''");
+ group.Property( "", "'$(EfcptConfigGenerationType)'==''");
+ group.Property( "", "'$(EfcptConfigUseDatabaseNames)'==''");
+ group.Property( "", "'$(EfcptConfigUseDataAnnotations)'==''");
+ group.Property( "", "'$(EfcptConfigUseInflector)'==''");
+ group.Property( "", "'$(EfcptConfigUseLegacyInflector)'==''");
+ group.Property( "", "'$(EfcptConfigUseManyToManyEntity)'==''");
+ group.Property( "", "'$(EfcptConfigUseT4)'==''");
+ group.Property( "", "'$(EfcptConfigUseT4Split)'==''");
+ group.Property( "", "'$(EfcptConfigRemoveDefaultSqlFromBool)'==''");
+ group.Property( "", "'$(EfcptConfigSoftDeleteObsoleteFiles)'==''");
+ group.Property( "", "'$(EfcptConfigDiscoverMultipleResultSets)'==''");
+ group.Property( "", "'$(EfcptConfigUseAlternateResultSetDiscovery)'==''");
+ group.Property( "", "'$(EfcptConfigT4TemplatePath)'==''");
+ group.Property( "", "'$(EfcptConfigUseNoNavigations)'==''");
+ group.Property( "", "'$(EfcptConfigMergeDacpacs)'==''");
+ group.Property( "", "'$(EfcptConfigRefreshObjectLists)'==''");
+ group.Property( "", "'$(EfcptConfigGenerateMermaidDiagram)'==''");
+ group.Property( "", "'$(EfcptConfigUseDecimalAnnotationForSprocs)'==''");
+ group.Property( "", "'$(EfcptConfigUsePrefixNavigationNaming)'==''");
+ group.Property( "", "'$(EfcptConfigUseDatabaseNamesForRoutines)'==''");
+ group.Property( "", "'$(EfcptConfigUseInternalAccessForRoutines)'==''");
+ group.Property( "", "'$(EfcptConfigUseDateOnlyTimeOnly)'==''");
+ group.Property( "", "'$(EfcptConfigUseHierarchyId)'==''");
+ group.Property( "", "'$(EfcptConfigUseSpatial)'==''");
+ group.Property( "", "'$(EfcptConfigUseNodaTime)'==''");
+ group.Property( "", "'$(EfcptConfigPreserveCasingWithRegex)'==''");
+ group.Property( "false", "'$(EfcptEnableProfiling)'==''");
+ group.Property( "$(EfcptOutput)build-profile.json", "'$(EfcptProfilingOutput)'==''");
+ group.Property( "minimal", "'$(EfcptProfilingVerbosity)'==''");
+ });
+ t.PropertyGroup(null, group =>
+ {
+ group.Property( "microsoft-build-sql", "'$(EfcptSqlProjType)'==''");
+ group.Property( "csharp", "'$(EfcptSqlProjLanguage)'==''");
+ group.Property( "$(MSBuildProjectDirectory)\\", "'$(EfcptSqlProjOutputDir)'==''");
+ group.Property( "$(MSBuildProjectDirectory)\\", "'$(EfcptSqlScriptsDir)'==''");
+ group.Property( "Sql160", "'$(EfcptSqlServerVersion)'==''");
+ group.Property( "", "'$(EfcptSqlPackageToolVersion)'==''");
+ group.Property( "true", "'$(EfcptSqlPackageToolRestore)'==''");
+ group.Property( "", "'$(EfcptSqlPackageToolPath)'==''");
+ });
+ })
+ .Build();
+ }
+
+ // Strongly-typed property names
+
+
+ public readonly struct EfcptAppConfig : IMsBuildPropertyName
+ {
+ public string Name => "EfcptAppConfig";
+ }
+ public readonly struct EfcptApplyMsBuildOverrides : IMsBuildPropertyName
+ {
+ public string Name => "EfcptApplyMsBuildOverrides";
+ }
+ public readonly struct EfcptAppSettings : IMsBuildPropertyName
+ {
+ public string Name => "EfcptAppSettings";
+ }
+ public readonly struct EfcptAutoDetectWarningLevel : IMsBuildPropertyName
+ {
+ public string Name => "EfcptAutoDetectWarningLevel";
+ }
+ public readonly struct EfcptCheckForUpdates : IMsBuildPropertyName
+ {
+ public string Name => "EfcptCheckForUpdates";
+ }
+ public readonly struct EfcptConfig : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfig";
+ }
+ public readonly struct EfcptConfigDbContextName : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigDbContextName";
+ }
+ public readonly struct EfcptConfigDbContextNamespace : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigDbContextNamespace";
+ }
+ public readonly struct EfcptConfigDbContextOutputPath : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigDbContextOutputPath";
+ }
+ public readonly struct EfcptConfigDiscoverMultipleResultSets : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigDiscoverMultipleResultSets";
+ }
+ public readonly struct EfcptConfigEnableOnConfiguring : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigEnableOnConfiguring";
+ }
+ public readonly struct EfcptConfigGenerateMermaidDiagram : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigGenerateMermaidDiagram";
+ }
+ public readonly struct EfcptConfigGenerationType : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigGenerationType";
+ }
+ public readonly struct EfcptConfigMergeDacpacs : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigMergeDacpacs";
+ }
+ public readonly struct EfcptConfigModelNamespace : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigModelNamespace";
+ }
+ public readonly struct EfcptConfigOutputPath : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigOutputPath";
+ }
+ public readonly struct EfcptConfigPreserveCasingWithRegex : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigPreserveCasingWithRegex";
+ }
+ public readonly struct EfcptConfigRefreshObjectLists : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigRefreshObjectLists";
+ }
+ public readonly struct EfcptConfigRemoveDefaultSqlFromBool : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigRemoveDefaultSqlFromBool";
+ }
+ public readonly struct EfcptConfigRootNamespace : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigRootNamespace";
+ }
+ public readonly struct EfcptConfigSoftDeleteObsoleteFiles : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigSoftDeleteObsoleteFiles";
+ }
+ public readonly struct EfcptConfigSplitDbContext : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigSplitDbContext";
+ }
+ public readonly struct EfcptConfigT4TemplatePath : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigT4TemplatePath";
+ }
+ public readonly struct EfcptConfigUseAlternateResultSetDiscovery : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigUseAlternateResultSetDiscovery";
+ }
+ public readonly struct EfcptConfigUseDataAnnotations : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigUseDataAnnotations";
+ }
+ public readonly struct EfcptConfigUseDatabaseNames : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigUseDatabaseNames";
+ }
+ public readonly struct EfcptConfigUseDatabaseNamesForRoutines : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigUseDatabaseNamesForRoutines";
+ }
+ public readonly struct EfcptConfigUseDateOnlyTimeOnly : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigUseDateOnlyTimeOnly";
+ }
+ public readonly struct EfcptConfigUseDecimalAnnotationForSprocs : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigUseDecimalAnnotationForSprocs";
+ }
+ public readonly struct EfcptConfigUseHierarchyId : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigUseHierarchyId";
+ }
+ public readonly struct EfcptConfigUseInflector : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigUseInflector";
+ }
+ public readonly struct EfcptConfigUseInternalAccessForRoutines : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigUseInternalAccessForRoutines";
+ }
+ public readonly struct EfcptConfigUseLegacyInflector : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigUseLegacyInflector";
+ }
+ public readonly struct EfcptConfigUseManyToManyEntity : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigUseManyToManyEntity";
+ }
+ public readonly struct EfcptConfigUseNodaTime : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigUseNodaTime";
+ }
+ public readonly struct EfcptConfigUseNoNavigations : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigUseNoNavigations";
+ }
+ public readonly struct EfcptConfigUsePrefixNavigationNaming : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigUsePrefixNavigationNaming";
+ }
+ public readonly struct EfcptConfigUseSchemaFolders : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigUseSchemaFolders";
+ }
+ public readonly struct EfcptConfigUseSchemaNamespaces : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigUseSchemaNamespaces";
+ }
+ public readonly struct EfcptConfigUseSpatial : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigUseSpatial";
+ }
+ public readonly struct EfcptConfigUseT4 : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigUseT4";
+ }
+ public readonly struct EfcptConfigUseT4Split : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigUseT4Split";
+ }
+ public readonly struct EfcptConnectionString : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConnectionString";
+ }
+ public readonly struct EfcptConnectionStringName : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConnectionStringName";
+ }
+ public readonly struct EfcptDacpac : IMsBuildPropertyName
+ {
+ public string Name => "EfcptDacpac";
+ }
+ public readonly struct EfcptDataProject : IMsBuildPropertyName
+ {
+ public string Name => "EfcptDataProject";
+ }
+ public readonly struct EfcptDataProjectOutputSubdir : IMsBuildPropertyName
+ {
+ public string Name => "EfcptDataProjectOutputSubdir";
+ }
+ public readonly struct EfcptDetectGeneratedFileChanges : IMsBuildPropertyName
+ {
+ public string Name => "EfcptDetectGeneratedFileChanges";
+ }
+ public readonly struct EfcptDotNetExe : IMsBuildPropertyName
+ {
+ public string Name => "EfcptDotNetExe";
+ }
+ public readonly struct EfcptDumpResolvedInputs : IMsBuildPropertyName
+ {
+ public string Name => "EfcptDumpResolvedInputs";
+ }
+ public readonly struct EfcptEnabled : IMsBuildPropertyName
+ {
+ public string Name => "EfcptEnabled";
+ }
+ public readonly struct EfcptEnableProfiling : IMsBuildPropertyName
+ {
+ public string Name => "EfcptEnableProfiling";
+ }
+ public readonly struct EfcptExternalDataDir : IMsBuildPropertyName
+ {
+ public string Name => "EfcptExternalDataDir";
+ }
+ public readonly struct EfcptFingerprintFile : IMsBuildPropertyName
+ {
+ public string Name => "EfcptFingerprintFile";
+ }
+ public readonly struct EfcptForceUpdateCheck : IMsBuildPropertyName
+ {
+ public string Name => "EfcptForceUpdateCheck";
+ }
+ public readonly struct EfcptGeneratedDir : IMsBuildPropertyName
+ {
+ public string Name => "EfcptGeneratedDir";
+ }
+ public readonly struct EfcptLogVerbosity : IMsBuildPropertyName
+ {
+ public string Name => "EfcptLogVerbosity";
+ }
+ public readonly struct EfcptOutput : IMsBuildPropertyName
+ {
+ public string Name => "EfcptOutput";
+ }
+ public readonly struct EfcptProbeSolutionDir : IMsBuildPropertyName
+ {
+ public string Name => "EfcptProbeSolutionDir";
+ }
+ public readonly struct EfcptProfilingOutput : IMsBuildPropertyName
+ {
+ public string Name => "EfcptProfilingOutput";
+ }
+ public readonly struct EfcptProfilingVerbosity : IMsBuildPropertyName
+ {
+ public string Name => "EfcptProfilingVerbosity";
+ }
+ public readonly struct EfcptProvider : IMsBuildPropertyName
+ {
+ public string Name => "EfcptProvider";
+ }
+ public readonly struct EfcptRenaming : IMsBuildPropertyName
+ {
+ public string Name => "EfcptRenaming";
+ }
+ public readonly struct EfcptSdkVersionWarningLevel : IMsBuildPropertyName
+ {
+ public string Name => "EfcptSdkVersionWarningLevel";
+ }
+ public readonly struct EfcptSolutionDir : IMsBuildPropertyName
+ {
+ public string Name => "EfcptSolutionDir";
+ }
+ public readonly struct EfcptSolutionPath : IMsBuildPropertyName
+ {
+ public string Name => "EfcptSolutionPath";
+ }
+ public readonly struct EfcptSplitOutputs : IMsBuildPropertyName
+ {
+ public string Name => "EfcptSplitOutputs";
+ }
+ public readonly struct EfcptSqlPackageToolPath : IMsBuildPropertyName
+ {
+ public string Name => "EfcptSqlPackageToolPath";
+ }
+ public readonly struct EfcptSqlPackageToolRestore : IMsBuildPropertyName
+ {
+ public string Name => "EfcptSqlPackageToolRestore";
+ }
+ public readonly struct EfcptSqlPackageToolVersion : IMsBuildPropertyName
+ {
+ public string Name => "EfcptSqlPackageToolVersion";
+ }
+ public readonly struct EfcptSqlProj : IMsBuildPropertyName
+ {
+ public string Name => "EfcptSqlProj";
+ }
+ public readonly struct EfcptSqlProjLanguage : IMsBuildPropertyName
+ {
+ public string Name => "EfcptSqlProjLanguage";
+ }
+ public readonly struct EfcptSqlProjOutputDir : IMsBuildPropertyName
+ {
+ public string Name => "EfcptSqlProjOutputDir";
+ }
+ public readonly struct EfcptSqlProjType : IMsBuildPropertyName
+ {
+ public string Name => "EfcptSqlProjType";
+ }
+ public readonly struct EfcptSqlScriptsDir : IMsBuildPropertyName
+ {
+ public string Name => "EfcptSqlScriptsDir";
+ }
+ public readonly struct EfcptSqlServerVersion : IMsBuildPropertyName
+ {
+ public string Name => "EfcptSqlServerVersion";
+ }
+ public readonly struct EfcptStampFile : IMsBuildPropertyName
+ {
+ public string Name => "EfcptStampFile";
+ }
+ public readonly struct EfcptTemplateDir : IMsBuildPropertyName
+ {
+ public string Name => "EfcptTemplateDir";
+ }
+ public readonly struct EfcptToolCommand : IMsBuildPropertyName
+ {
+ public string Name => "EfcptToolCommand";
+ }
+ public readonly struct EfcptToolMode : IMsBuildPropertyName
+ {
+ public string Name => "EfcptToolMode";
+ }
+ public readonly struct EfcptToolPackageId : IMsBuildPropertyName
+ {
+ public string Name => "EfcptToolPackageId";
+ }
+ public readonly struct EfcptToolPath : IMsBuildPropertyName
+ {
+ public string Name => "EfcptToolPath";
+ }
+ public readonly struct EfcptToolRestore : IMsBuildPropertyName
+ {
+ public string Name => "EfcptToolRestore";
+ }
+ public readonly struct EfcptToolVersion : IMsBuildPropertyName
+ {
+ public string Name => "EfcptToolVersion";
+ }
+ public readonly struct EfcptUpdateCheckCacheHours : IMsBuildPropertyName
+ {
+ public string Name => "EfcptUpdateCheckCacheHours";
+ }
+}
+
+
+
+
+
diff --git a/src/JD.Efcpt.Build.Definitions/BuildTransitiveTargetsFactory.cs b/src/JD.Efcpt.Build.Definitions/BuildTransitiveTargetsFactory.cs
new file mode 100644
index 0000000..1e7b13b
--- /dev/null
+++ b/src/JD.Efcpt.Build.Definitions/BuildTransitiveTargetsFactory.cs
@@ -0,0 +1,817 @@
+using JD.Efcpt.Build.Definitions.Constants;
+using JD.Efcpt.Build.Definitions.Registry;
+using JD.Efcpt.Build.Definitions.Shared;
+using JD.MSBuild.Fluent;
+using JD.MSBuild.Fluent.Common;
+using JD.MSBuild.Fluent.Fluent;
+using JD.MSBuild.Fluent.Typed;
+
+namespace JD.Efcpt.Build.Definitions;
+
+///
+/// MSBuild package definition scaffolded from JD.Efcpt.Build.xml
+///
+public static class BuildTransitiveTargetsFactory
+{
+ public static PackageDefinition Create()
+ {
+ return Package.Define("JD.Efcpt.Build")
+ .Props(p =>
+ {
+ p.PropertyGroup(null, SharedPropertyGroups.ConfigureNullableReferenceTypes);
+ p.PropertyGroup(null, SharedPropertyGroups.ConfigureTaskAssemblyResolution);
+ })
+ .Targets(t =>
+ {
+ t.PropertyGroup(null, SharedPropertyGroups.ConfigureNullableReferenceTypes);
+ t.PropertyGroup(null, SharedPropertyGroups.ConfigureTaskAssemblyResolution);
+
+ t.Target("_EfcptDetectSqlProject", target =>
+ {
+ target.BeforeTargets("BeforeBuild", "BeforeRebuild");
+ target.Task("DetectSqlProject", task =>
+ {
+ task.Param("ProjectPath", "$(MSBuildProjectFullPath)");
+ task.Param("SqlServerVersion", "$(SqlServerVersion)");
+ task.Param("DSP", "$(DSP)");
+ task.OutputProperty();
+ });
+ target.PropertyGroup("'$(_EfcptIsSqlProject)' == ''", group =>
+ {
+ group.Property("_EfcptIsSqlProject", "false");
+ });
+ });
+ t.Target("_EfcptLogTaskAssemblyInfo", target =>
+ {
+ target.BeforeTargets(new EfcptResolveInputsTarget(), new EfcptResolveInputsForDirectDacpacTarget());
+ target.Condition("'$(EfcptEnabled)' == 'true' and '$(EfcptLogVerbosity)' == 'detailed'");
+ target.Message("EFCPT Task Assembly Selection:", "high");
+ target.Message(" MSBuildRuntimeType: $(MSBuildRuntimeType)", "high");
+ target.Message(" MSBuildVersion: $(MSBuildVersion)", "high");
+ target.Message(" Selected TasksFolder: $(_EfcptTasksFolder)", "high");
+ target.Message(" TaskAssembly Path: $(_EfcptTaskAssembly)", "high");
+ target.Message(" TaskAssembly Exists: $([System.IO.File]::Exists('$(_EfcptTaskAssembly)'))", "high");
+ });
+
+ UsingTasksRegistry.RegisterAll(t);
+
+ t.Target("_EfcptInitializeProfiling", target =>
+ {
+ target.BeforeTargets("_EfcptDetectSqlProject");
+ target.Condition("'$(EfcptEnabled)' == 'true'");
+ target.Task("InitializeBuildProfiling", task =>
+ {
+ task.Param("EnableProfiling", "$(EfcptEnableProfiling)");
+ task.Param("ProjectPath", "$(MSBuildProjectFullPath)");
+ task.Param("ProjectName", "$(MSBuildProjectName)");
+ task.Param("TargetFramework", "$(TargetFramework)");
+ task.Param("Configuration", "$(Configuration)");
+ task.Param("ConfigPath", "$(_EfcptResolvedConfig)");
+ task.Param("RenamingPath", "$(_EfcptResolvedRenaming)");
+ task.Param("TemplateDir", "$(_EfcptResolvedTemplateDir)");
+ task.Param("SqlProjectPath", "$(_EfcptSqlProj)");
+ task.Param("DacpacPath", "$(_EfcptDacpacPath)");
+ task.Param("Provider", "$(EfcptProvider)");
+ });
+ });
+ t.Target("_EfcptCheckForUpdates", target =>
+ {
+ target.BeforeTargets("Build");
+ target.Condition("'$(EfcptCheckForUpdates)' == 'true' and '$(EfcptSdkVersion)' != ''");
+ target.Task("CheckSdkVersion", task =>
+ {
+ task.Param("CurrentVersion", "$(EfcptSdkVersion)");
+ task.Param("PackageId", "JD.Efcpt.Sdk");
+ task.Param("CacheHours", "$(EfcptUpdateCheckCacheHours)");
+ task.Param("ForceCheck", "$(EfcptForceUpdateCheck)");
+ task.Param("WarningLevel", "$(EfcptSdkVersionWarningLevel)");
+ task.OutputProperty();
+ task.OutputProperty();
+ });
+ });
+ t.Target( target =>
+ {
+ target.Condition("'$(EfcptEnabled)' == 'true' and '$(_EfcptIsSqlProject)' == 'true'");
+ });
+ t.Target( target =>
+ {
+ target.DependsOnTargets("BeforeSqlProjGeneration");
+ target.Condition("'$(EfcptEnabled)' == 'true' and '$(_EfcptIsSqlProject)' == 'true'");
+ target.Error("SqlProj generation requires a connection string. Set EfcptConnectionString, EfcptAppSettings, or EfcptAppConfig.", "'$(EfcptConnectionString)' == '' and '$(EfcptAppSettings)' == '' and '$(EfcptAppConfig)' == ''");
+ target.Message("Querying database schema for fingerprinting...", "high");
+ target.Task("QuerySchemaMetadata", task =>
+ {
+ task.Param("ConnectionString", "$(EfcptConnectionString)");
+ task.Param("OutputDir", "$(EfcptOutput)");
+ task.Param("Provider", "$(EfcptProvider)");
+ task.Param("LogVerbosity", "$(EfcptLogVerbosity)");
+ task.OutputProperty();
+ });
+ target.Message("Database schema fingerprint: $(_EfcptSchemaFingerprint)", "normal");
+ });
+ t.Target( target =>
+ {
+ target.DependsOnTargets("EfcptQueryDatabaseSchemaForSqlProj");
+ target.Condition("'$(EfcptEnabled)' == 'true' and '$(_EfcptIsSqlProject)' == 'true'");
+ target.PropertyGroup(null, group =>
+ {
+ group.Property("_EfcptScriptsDir", "$(EfcptSqlScriptsDir)");
+ });
+ target.Message("Extracting database schema to SQL scripts in SQL project: $(_EfcptScriptsDir)", "high");
+ target.ItemGroup(null, group =>
+ {
+ group.Include("_EfcptGeneratedScripts", "$(_EfcptScriptsDir)**\\*.sql");
+ });
+ target.Task("Delete", task =>
+ {
+ task.Param("Files", "@(_EfcptGeneratedScripts)");
+ }, "'@(_EfcptGeneratedScripts)' != ''");
+ target.Task("RunSqlPackage", task =>
+ {
+ task.Param("ToolVersion", "$(EfcptSqlPackageToolVersion)");
+ task.Param("ToolRestore", "$(EfcptSqlPackageToolRestore)");
+ task.Param("ToolPath", "$(EfcptSqlPackageToolPath)");
+ task.Param("DotNetExe", "$(EfcptDotNetExe)");
+ task.Param("WorkingDirectory", "$(EfcptOutput)");
+ task.Param("ConnectionString", "$(EfcptConnectionString)");
+ task.Param("TargetDirectory", "$(_EfcptScriptsDir)");
+ task.Param("ExtractTarget", "SchemaObjectType");
+ task.Param("TargetFramework", "$(TargetFramework)");
+ task.Param("LogVerbosity", "$(EfcptLogVerbosity)");
+ task.OutputProperty();
+ });
+ target.Message("Extracted SQL scripts to: $(_EfcptExtractedScriptsPath)", "high");
+ });
+ t.Target( target =>
+ {
+ target.DependsOnTargets("EfcptExtractDatabaseSchemaToScripts");
+ target.Condition("'$(EfcptEnabled)' == 'true' and '$(_EfcptIsSqlProject)' == 'true'");
+ target.Message("Adding auto-generation warnings to SQL files...", "high");
+ target.PropertyGroup(null, group =>
+ {
+ group.Property("_EfcptDatabaseName", "$([System.Text.RegularExpressions.Regex]::Match($(EfcptConnectionString), 'Database\\s*=\\s*\\\"?([^;\"]+)\\\"?').Groups[1].Value)");
+ group.Property("_EfcptDatabaseName", "$([System.Text.RegularExpressions.Regex]::Match($(EfcptConnectionString), 'Initial Catalog\\s*=\\s*\\\"?([^;\"]+)\\\"?').Groups[1].Value)");
+ });
+ target.Task("AddSqlFileWarnings", task =>
+ {
+ task.Param("ScriptsDirectory", "$(_EfcptScriptsDir)");
+ task.Param("DatabaseName", "$(_EfcptDatabaseName)");
+ task.Param("LogVerbosity", "$(EfcptLogVerbosity)");
+ });
+ });
+ t.Target( target =>
+ {
+ target.BeforeTargets("Build");
+ target.DependsOnTargets("EfcptAddSqlFileWarnings");
+ target.Condition("'$(EfcptEnabled)' == 'true' and '$(_EfcptIsSqlProject)' == 'true'");
+ target.Message("_EfcptIsSqlProject: $(_EfcptIsSqlProject)", "high");
+ target.Message("SQL script generation complete. SQL project will build to DACPAC.", "high");
+ });
+ t.Target( target =>
+ {
+ target.Condition("'$(EfcptEnabled)' == 'true' and '$(_EfcptIsSqlProject)' != 'true' and '$(EfcptDacpac)' == ''");
+ target.Task("ResolveSqlProjAndInputs", task =>
+ {
+ task.Param("ProjectFullPath", "$(MSBuildProjectFullPath)");
+ task.Param("ProjectDirectory", "$(MSBuildProjectDirectory)");
+ task.Param("Configuration", "$(Configuration)");
+ task.Param("ProjectReferences", "@(ProjectReference)");
+ task.Param("SqlProjOverride", "$(EfcptSqlProj)");
+ task.Param("ConfigOverride", "$(EfcptConfig)");
+ task.Param("RenamingOverride", "$(EfcptRenaming)");
+ task.Param("TemplateDirOverride", "$(EfcptTemplateDir)");
+ task.Param("SolutionDir", "$(EfcptSolutionDir)");
+ task.Param("SolutionPath", "$(EfcptSolutionPath)");
+ task.Param("ProbeSolutionDir", "$(EfcptProbeSolutionDir)");
+ task.Param("OutputDir", "$(EfcptOutput)");
+ task.Param("DefaultsRoot", "$(MSBuildThisFileDirectory)Defaults");
+ task.Param("DumpResolvedInputs", "$(EfcptDumpResolvedInputs)");
+ task.Param("EfcptConnectionString", "$(EfcptConnectionString)");
+ task.Param("EfcptAppSettings", "$(EfcptAppSettings)");
+ task.Param("EfcptAppConfig", "$(EfcptAppConfig)");
+ task.Param("EfcptConnectionStringName", "$(EfcptConnectionStringName)");
+ task.Param("AutoDetectWarningLevel", "$(EfcptAutoDetectWarningLevel)");
+ task.OutputProperty();
+ task.OutputProperty();
+ task.OutputProperty();
+ task.OutputProperty();
+ task.OutputProperty();
+ task.OutputProperty();
+ task.OutputProperty();
+ });
+ });
+ t.Target( target =>
+ {
+ target.Condition("'$(EfcptEnabled)' == 'true' and '$(EfcptDacpac)' != ''");
+ target.PropertyGroup(null, group =>
+ {
+ group.Property("_EfcptResolvedConfig", "$(MSBuildProjectDirectory)\\$(EfcptConfig)");
+ group.Property("_EfcptResolvedConfig", "$(MSBuildThisFileDirectory)Defaults\\efcpt-config.json");
+ group.Property("_EfcptResolvedRenaming", "$(MSBuildProjectDirectory)\\$(EfcptRenaming)");
+ group.Property("_EfcptResolvedRenaming", "$(MSBuildThisFileDirectory)Defaults\\efcpt.renaming.json");
+ group.Property("_EfcptResolvedTemplateDir", "$(MSBuildProjectDirectory)\\$(EfcptTemplateDir)");
+ group.Property("_EfcptResolvedTemplateDir", "$(MSBuildThisFileDirectory)Defaults\\Template");
+ group.Property("_EfcptIsUsingDefaultConfig", "true");
+ group.Property("_EfcptUseConnectionString", "false");
+ });
+ target.Task("MakeDir", task =>
+ {
+ task.Param("Directories", "$(EfcptOutput)");
+ });
+ });
+ t.Target( target =>
+ {
+ target.BeforeTargets(new EfcptStageInputsTarget());
+ target.AfterTargets(new EfcptResolveInputsTarget());
+ target.Condition("'$(EfcptEnabled)' == 'true' and '$(_EfcptUseConnectionString)' == 'true'");
+ target.Task("QuerySchemaMetadata", task =>
+ {
+ task.Param("ConnectionString", "$(_EfcptResolvedConnectionString)");
+ task.Param("OutputDir", "$(EfcptOutput)");
+ task.Param("Provider", "$(EfcptProvider)");
+ task.Param("LogVerbosity", "$(EfcptLogVerbosity)");
+ task.OutputProperty();
+ });
+ });
+ t.Target( target =>
+ {
+ target.DependsOnTargets("EfcptResolveInputs;EfcptResolveInputsForDirectDacpac");
+ target.Condition("'$(EfcptEnabled)' == 'true' and '$(_EfcptUseConnectionString)' != 'true' and '$(EfcptDacpac)' != ''");
+ target.PropertyGroup(null, group =>
+ {
+ group.Property("_EfcptDacpacPath", "$(EfcptDacpac)");
+ group.Property("_EfcptDacpacPath", "$([System.IO.Path]::GetFullPath($([System.IO.Path]::Combine('$(MSBuildProjectDirectory)', '$(EfcptDacpac)'))))");
+ group.Property("_EfcptUseDirectDacpac", "true");
+ });
+ target.Error("EfcptDacpac was specified but the file does not exist: $(_EfcptDacpacPath)", "!Exists('$(_EfcptDacpacPath)')");
+ target.Message("Using pre-built DACPAC: $(_EfcptDacpacPath)", "high");
+ });
+ t.Target( target =>
+ {
+ target.DependsOnTargets("EfcptResolveInputs;EfcptUseDirectDacpac");
+ target.Condition("'$(EfcptEnabled)' == 'true'");
+ target.Message("Building SQL project: $(_EfcptSqlProj)", "normal", "'$(_EfcptUseConnectionString)' != 'true' and '$(_EfcptUseDirectDacpac)' != 'true' and '$(_EfcptSqlProj)' != ''");
+ target.Task("MSBuild", task =>
+ {
+ task.Param("Projects", "$(_EfcptSqlProj)");
+ task.Param("Targets", "Build");
+ task.Param("Properties", "Configuration=$(Configuration)");
+ task.Param("BuildInParallel", "false");
+ }, "'$(_EfcptUseConnectionString)' != 'true' and '$(_EfcptUseDirectDacpac)' != 'true' and '$(_EfcptSqlProj)' != ''");
+ });
+ t.Target( target =>
+ {
+ target.DependsOnTargets("EfcptResolveInputs;EfcptUseDirectDacpac;EfcptBuildSqlProj");
+ target.Condition("'$(EfcptEnabled)' == 'true'");
+ target.Task("EnsureDacpacBuilt", task =>
+ {
+ task.Param("SqlProjPath", "$(_EfcptSqlProj)");
+ task.Param("Configuration", "$(Configuration)");
+ task.Param("MsBuildExe", "$(MSBuildBinPath)msbuild.exe");
+ task.Param("DotNetExe", "$(EfcptDotNetExe)");
+ task.Param("LogVerbosity", "$(EfcptLogVerbosity)");
+ task.OutputProperty();
+ }, "'$(_EfcptUseConnectionString)' != 'true' and '$(_EfcptUseDirectDacpac)' != 'true' and '$(_EfcptIsSqlProject)' != 'true'");
+ });
+ t.Target( target =>
+ {
+ target.DependsOnTargets("EfcptResolveInputs;EfcptEnsureDacpac;EfcptUseDirectDacpac");
+ target.Condition("'$(EfcptEnabled)' == 'true' and '$(_EfcptIsSqlProject)' != 'true'");
+ target.Task("ResolveDbContextName", task =>
+ {
+ task.Param("ExplicitDbContextName", "$(EfcptConfigDbContextName)");
+ task.Param("SqlProjPath", "$(_EfcptSqlProj)");
+ task.Param("DacpacPath", "$(_EfcptDacpacPath)");
+ task.Param("ConnectionString", "$(_EfcptResolvedConnectionString)");
+ task.Param("UseConnectionStringMode", "$(_EfcptUseConnectionString)");
+ task.Param("LogVerbosity", "$(EfcptLogVerbosity)");
+ task.OutputProperty();
+ });
+ target.PropertyGroup(null, group =>
+ {
+ group.Property( "$(_EfcptResolvedDbContextName)");
+ });
+ });
+ t.Target( target =>
+ {
+ target.DependsOnTargets("EfcptResolveInputs;EfcptEnsureDacpac;EfcptUseDirectDacpac;EfcptResolveDbContextName");
+ target.Condition("'$(EfcptEnabled)' == 'true' and '$(_EfcptIsSqlProject)' != 'true'");
+ target.Task("StageEfcptInputs", task =>
+ {
+ task.Param("OutputDir", "$(EfcptOutput)");
+ task.Param("ProjectDirectory", "$(MSBuildProjectDirectory)");
+ task.Param("ConfigPath", "$(_EfcptResolvedConfig)");
+ task.Param("RenamingPath", "$(_EfcptResolvedRenaming)");
+ task.Param("TemplateDir", "$(_EfcptResolvedTemplateDir)");
+ task.Param("TemplateOutputDir", "$(EfcptGeneratedDir)");
+ task.Param("TargetFramework", "$(TargetFramework)");
+ task.Param("LogVerbosity", "$(EfcptLogVerbosity)");
+ task.OutputProperty();
+ task.OutputProperty();
+ task.OutputProperty();
+ });
+ });
+ t.Target( target =>
+ {
+ target.DependsOnTargets("EfcptStageInputs");
+ target.Condition("'$(EfcptEnabled)' == 'true' and '$(_EfcptIsSqlProject)' != 'true'");
+ target.Task("ApplyConfigOverrides", task =>
+ {
+ task.Param("StagedConfigPath", "$(_EfcptStagedConfig)");
+ task.Param("ApplyOverrides", "$(EfcptApplyMsBuildOverrides)");
+ task.Param("IsUsingDefaultConfig", "$(_EfcptIsUsingDefaultConfig)");
+ task.Param("LogVerbosity", "$(EfcptLogVerbosity)");
+ task.Param("RootNamespace", "$(EfcptConfigRootNamespace)");
+ task.Param("DbContextName", "$(EfcptConfigDbContextName)");
+ task.Param("DbContextNamespace", "$(EfcptConfigDbContextNamespace)");
+ task.Param("ModelNamespace", "$(EfcptConfigModelNamespace)");
+ task.Param("OutputPath", "$(EfcptConfigOutputPath)");
+ task.Param("DbContextOutputPath", "$(EfcptConfigDbContextOutputPath)");
+ task.Param("SplitDbContext", "$(EfcptConfigSplitDbContext)");
+ task.Param("UseSchemaFolders", "$(EfcptConfigUseSchemaFolders)");
+ task.Param("UseSchemaNamespaces", "$(EfcptConfigUseSchemaNamespaces)");
+ task.Param("EnableOnConfiguring", "$(EfcptConfigEnableOnConfiguring)");
+ task.Param("GenerationType", "$(EfcptConfigGenerationType)");
+ task.Param("UseDatabaseNames", "$(EfcptConfigUseDatabaseNames)");
+ task.Param("UseDataAnnotations", "$(EfcptConfigUseDataAnnotations)");
+ task.Param("UseNullableReferenceTypes", "$(EfcptConfigUseNullableReferenceTypes)");
+ task.Param("UseInflector", "$(EfcptConfigUseInflector)");
+ task.Param("UseLegacyInflector", "$(EfcptConfigUseLegacyInflector)");
+ task.Param("UseManyToManyEntity", "$(EfcptConfigUseManyToManyEntity)");
+ task.Param("UseT4", "$(EfcptConfigUseT4)");
+ task.Param("UseT4Split", "$(EfcptConfigUseT4Split)");
+ task.Param("RemoveDefaultSqlFromBool", "$(EfcptConfigRemoveDefaultSqlFromBool)");
+ task.Param("SoftDeleteObsoleteFiles", "$(EfcptConfigSoftDeleteObsoleteFiles)");
+ task.Param("DiscoverMultipleResultSets", "$(EfcptConfigDiscoverMultipleResultSets)");
+ task.Param("UseAlternateResultSetDiscovery", "$(EfcptConfigUseAlternateResultSetDiscovery)");
+ task.Param("T4TemplatePath", "$(EfcptConfigT4TemplatePath)");
+ task.Param("UseNoNavigations", "$(EfcptConfigUseNoNavigations)");
+ task.Param("MergeDacpacs", "$(EfcptConfigMergeDacpacs)");
+ task.Param("RefreshObjectLists", "$(EfcptConfigRefreshObjectLists)");
+ task.Param("GenerateMermaidDiagram", "$(EfcptConfigGenerateMermaidDiagram)");
+ task.Param("UseDecimalAnnotationForSprocs", "$(EfcptConfigUseDecimalAnnotationForSprocs)");
+ task.Param("UsePrefixNavigationNaming", "$(EfcptConfigUsePrefixNavigationNaming)");
+ task.Param("UseDatabaseNamesForRoutines", "$(EfcptConfigUseDatabaseNamesForRoutines)");
+ task.Param("UseInternalAccessForRoutines", "$(EfcptConfigUseInternalAccessForRoutines)");
+ task.Param("UseDateOnlyTimeOnly", "$(EfcptConfigUseDateOnlyTimeOnly)");
+ task.Param("UseHierarchyId", "$(EfcptConfigUseHierarchyId)");
+ task.Param("UseSpatial", "$(EfcptConfigUseSpatial)");
+ task.Param("UseNodaTime", "$(EfcptConfigUseNodaTime)");
+ task.Param("PreserveCasingWithRegex", "$(EfcptConfigPreserveCasingWithRegex)");
+ });
+ });
+ t.Target( target =>
+ {
+ target.DependsOnTargets("EfcptApplyConfigOverrides");
+ target.Condition("'$(EfcptEnabled)' == 'true' and '$(_EfcptIsSqlProject)' != 'true'");
+ target.Task("SerializeConfigProperties", task =>
+ {
+ task.Param("RootNamespace", "$(EfcptConfigRootNamespace)");
+ task.Param("DbContextName", "$(EfcptConfigDbContextName)");
+ task.Param("DbContextNamespace", "$(EfcptConfigDbContextNamespace)");
+ task.Param("ModelNamespace", "$(EfcptConfigModelNamespace)");
+ task.Param("OutputPath", "$(EfcptConfigOutputPath)");
+ task.Param("DbContextOutputPath", "$(EfcptConfigDbContextOutputPath)");
+ task.Param("SplitDbContext", "$(EfcptConfigSplitDbContext)");
+ task.Param("UseSchemaFolders", "$(EfcptConfigUseSchemaFolders)");
+ task.Param("UseSchemaNamespaces", "$(EfcptConfigUseSchemaNamespaces)");
+ task.Param("EnableOnConfiguring", "$(EfcptConfigEnableOnConfiguring)");
+ task.Param("GenerationType", "$(EfcptConfigGenerationType)");
+ task.Param("UseDatabaseNames", "$(EfcptConfigUseDatabaseNames)");
+ task.Param("UseDataAnnotations", "$(EfcptConfigUseDataAnnotations)");
+ task.Param("UseNullableReferenceTypes", "$(EfcptConfigUseNullableReferenceTypes)");
+ task.Param("UseInflector", "$(EfcptConfigUseInflector)");
+ task.Param("UseLegacyInflector", "$(EfcptConfigUseLegacyInflector)");
+ task.Param("UseManyToManyEntity", "$(EfcptConfigUseManyToManyEntity)");
+ task.Param("UseT4", "$(EfcptConfigUseT4)");
+ task.Param("UseT4Split", "$(EfcptConfigUseT4Split)");
+ task.Param("RemoveDefaultSqlFromBool", "$(EfcptConfigRemoveDefaultSqlFromBool)");
+ task.Param("SoftDeleteObsoleteFiles", "$(EfcptConfigSoftDeleteObsoleteFiles)");
+ task.Param("DiscoverMultipleResultSets", "$(EfcptConfigDiscoverMultipleResultSets)");
+ task.Param("UseAlternateResultSetDiscovery", "$(EfcptConfigUseAlternateResultSetDiscovery)");
+ task.Param("T4TemplatePath", "$(EfcptConfigT4TemplatePath)");
+ task.Param("UseNoNavigations", "$(EfcptConfigUseNoNavigations)");
+ task.Param("MergeDacpacs", "$(EfcptConfigMergeDacpacs)");
+ task.Param("RefreshObjectLists", "$(EfcptConfigRefreshObjectLists)");
+ task.Param("GenerateMermaidDiagram", "$(EfcptConfigGenerateMermaidDiagram)");
+ task.Param("UseDecimalAnnotationForSprocs", "$(EfcptConfigUseDecimalAnnotationForSprocs)");
+ task.Param("UsePrefixNavigationNaming", "$(EfcptConfigUsePrefixNavigationNaming)");
+ task.Param("UseDatabaseNamesForRoutines", "$(EfcptConfigUseDatabaseNamesForRoutines)");
+ task.Param("UseInternalAccessForRoutines", "$(EfcptConfigUseInternalAccessForRoutines)");
+ task.Param("UseDateOnlyTimeOnly", "$(EfcptConfigUseDateOnlyTimeOnly)");
+ task.Param("UseHierarchyId", "$(EfcptConfigUseHierarchyId)");
+ task.Param("UseSpatial", "$(EfcptConfigUseSpatial)");
+ task.Param("UseNodaTime", "$(EfcptConfigUseNodaTime)");
+ task.Param("PreserveCasingWithRegex", "$(EfcptConfigPreserveCasingWithRegex)");
+ task.OutputProperty();
+ });
+ });
+ t.Target( target =>
+ {
+ target.DependsOnTargets("EfcptSerializeConfigProperties");
+ target.Condition("'$(EfcptEnabled)' == 'true' and '$(_EfcptIsSqlProject)' != 'true'");
+ target.Task("ComputeFingerprint", task =>
+ {
+ task.Param("DacpacPath", "$(_EfcptDacpacPath)");
+ task.Param("SchemaFingerprint", "$(_EfcptSchemaFingerprint)");
+ task.Param("UseConnectionStringMode", "$(_EfcptUseConnectionString)");
+ task.Param("ConfigPath", "$(_EfcptStagedConfig)");
+ task.Param("RenamingPath", "$(_EfcptStagedRenaming)");
+ task.Param("TemplateDir", "$(_EfcptStagedTemplateDir)");
+ task.Param("FingerprintFile", "$(EfcptFingerprintFile)");
+ task.Param("ToolVersion", "$(EfcptToolVersion)");
+ task.Param("GeneratedDir", "$(EfcptGeneratedDir)");
+ task.Param("DetectGeneratedFileChanges", "$(EfcptDetectGeneratedFileChanges)");
+ task.Param("ConfigPropertyOverrides", "$(_EfcptSerializedConfigProperties)");
+ task.Param("LogVerbosity", "$(EfcptLogVerbosity)");
+ task.OutputProperty();
+ task.OutputProperty();
+ });
+ });
+ t.Target( target =>
+ {
+ target.DependsOnTargets("EfcptComputeFingerprint");
+ target.Condition("'$(EfcptEnabled)' == 'true' and '$(_EfcptIsSqlProject)' != 'true'");
+ });
+ t.Target( target =>
+ {
+ target.BeforeTargets("CoreCompile");
+ target.DependsOnTargets("BeforeEfcptGeneration");
+ target.Inputs("$(_EfcptDacpacPath);$(_EfcptStagedConfig);$(_EfcptStagedRenaming)");
+ target.Outputs("$(EfcptStampFile)");
+ target.Condition("'$(EfcptEnabled)' == 'true' and '$(_EfcptIsSqlProject)' != 'true' and ('$(_EfcptFingerprintChanged)' == 'true' or !Exists('$(EfcptStampFile)'))");
+ target.Task("MakeDir", task =>
+ {
+ task.Param("Directories", "$(EfcptGeneratedDir)");
+ });
+ target.Task("RunEfcpt", task =>
+ {
+ task.Param("ToolMode", "$(EfcptToolMode)");
+ task.Param("ToolPackageId", "$(EfcptToolPackageId)");
+ task.Param("ToolVersion", "$(EfcptToolVersion)");
+ task.Param("ToolRestore", "$(EfcptToolRestore)");
+ task.Param("ToolCommand", "$(EfcptToolCommand)");
+ task.Param("ToolPath", "$(EfcptToolPath)");
+ task.Param("DotNetExe", "$(EfcptDotNetExe)");
+ task.Param("WorkingDirectory", "$(EfcptOutput)");
+ task.Param("DacpacPath", "$(_EfcptDacpacPath)");
+ task.Param("ConnectionString", "$(_EfcptResolvedConnectionString)");
+ task.Param("UseConnectionStringMode", "$(_EfcptUseConnectionString)");
+ task.Param("Provider", "$(EfcptProvider)");
+ task.Param("ConfigPath", "$(_EfcptStagedConfig)");
+ task.Param("RenamingPath", "$(_EfcptStagedRenaming)");
+ task.Param("TemplateDir", "$(_EfcptStagedTemplateDir)");
+ task.Param("OutputDir", "$(EfcptGeneratedDir)");
+ task.Param("TargetFramework", "$(TargetFramework)");
+ task.Param("ProjectPath", "$(MSBuildProjectFullPath)");
+ task.Param("LogVerbosity", "$(EfcptLogVerbosity)");
+ });
+ target.Task("RenameGeneratedFiles", task =>
+ {
+ task.Param("GeneratedDir", "$(EfcptGeneratedDir)");
+ task.Param("LogVerbosity", "$(EfcptLogVerbosity)");
+ });
+ target.Task("WriteLinesToFile", task =>
+ {
+ task.Param("File", "$(EfcptStampFile)");
+ task.Param("Lines", "$(_EfcptFingerprint)");
+ task.Param("Overwrite", "true");
+ });
+ });
+ t.Target( target =>
+ {
+ target.AfterTargets(new EfcptGenerateModelsTarget());
+ target.Condition("'$(EfcptEnabled)' == 'true' and '$(_EfcptIsSqlProject)' != 'true'");
+ });
+ t.Target( target =>
+ {
+ target.DependsOnTargets("EfcptGenerateModels");
+ target.Condition("'$(EfcptEnabled)' == 'true' and '$(_EfcptIsSqlProject)' != 'true' and '$(EfcptSplitOutputs)' == 'true'");
+ target.PropertyGroup(null, group =>
+ {
+ group.Property("_EfcptDataProjectPath", "$(EfcptDataProject)");
+ group.Property("_EfcptDataProjectPath", "$([System.IO.Path]::GetFullPath($([System.IO.Path]::Combine('$(MSBuildProjectDirectory)', '$(EfcptDataProject)'))))");
+ });
+ target.Error("EfcptSplitOutputs is enabled but EfcptDataProject is not set. Please specify the path to your Data project: ..\\MyProject.Data\\MyProject.Data.csproj", "'$(_EfcptDataProjectPath)' == ''");
+ target.Error("EfcptDataProject was specified but the file does not exist: $(_EfcptDataProjectPath)", "!Exists('$(_EfcptDataProjectPath)')");
+ target.PropertyGroup(null, group =>
+ {
+ group.Property("_EfcptDataProjectDir", "$([System.IO.Path]::GetDirectoryName('$(_EfcptDataProjectPath)'))\\");
+ group.Property("_EfcptDataDestDir", "$(_EfcptDataProjectDir)$(EfcptDataProjectOutputSubdir)");
+ });
+ target.Message("Split outputs enabled. DbContext and configurations will be copied to: $(_EfcptDataDestDir)", "high");
+ });
+ t.Target( target =>
+ {
+ target.DependsOnTargets("EfcptValidateSplitOutputs");
+ target.Condition("'$(EfcptEnabled)' == 'true' and '$(_EfcptIsSqlProject)' != 'true' and '$(EfcptSplitOutputs)' == 'true'");
+ target.ItemGroup(null, group =>
+ {
+ group.Include("_EfcptDbContextFiles", "$(EfcptGeneratedDir)*.g.cs");
+ });
+ target.ItemGroup(null, group =>
+ {
+ group.Include("_EfcptConfigurationFiles", "$(EfcptGeneratedDir)*Configuration.g.cs");
+ group.Include("_EfcptConfigurationFiles", "$(EfcptGeneratedDir)Configurations\\**\\*.g.cs");
+ });
+ target.PropertyGroup(null, group =>
+ {
+ group.Property("_EfcptHasFilesToCopy", "true");
+ });
+ target.Task("RemoveDir", task =>
+ {
+ task.Param("Directories", "$(_EfcptDataDestDir)");
+ }, "'$(_EfcptHasFilesToCopy)' == 'true' and Exists('$(_EfcptDataDestDir)')");
+ target.Task("MakeDir", task =>
+ {
+ task.Param("Directories", "$(_EfcptDataDestDir)");
+ }, "'$(_EfcptHasFilesToCopy)' == 'true'");
+ target.Task("MakeDir", task =>
+ {
+ task.Param("Directories", "$(_EfcptDataDestDir)Configurations");
+ }, "'@(_EfcptConfigurationFiles)' != ''");
+ target.Task("Copy", task =>
+ {
+ task.Param("SourceFiles", "@(_EfcptDbContextFiles)");
+ task.Param("DestinationFolder", "$(_EfcptDataDestDir)");
+ task.Param("SkipUnchangedFiles", "true");
+ task.OutputItem("CopiedFiles", "_EfcptCopiedDataFiles");
+ }, "'@(_EfcptDbContextFiles)' != ''");
+ target.Task("Copy", task =>
+ {
+ task.Param("SourceFiles", "@(_EfcptConfigurationFiles)");
+ task.Param("DestinationFolder", "$(_EfcptDataDestDir)Configurations");
+ task.Param("SkipUnchangedFiles", "true");
+ task.OutputItem("CopiedFiles", "_EfcptCopiedDataFiles");
+ }, "'@(_EfcptConfigurationFiles)' != ''");
+ target.Message("Copied @(_EfcptCopiedDataFiles->Count()) data files to Data project: $(_EfcptDataDestDir)", "high", "'@(_EfcptCopiedDataFiles)' != ''");
+ target.Message("Split outputs: No new files to copy (generation was skipped)", "normal", "'$(_EfcptHasFilesToCopy)' != 'true'");
+ target.Task("Delete", task =>
+ {
+ task.Param("Files", "@(_EfcptDbContextFiles)");
+ }, "'@(_EfcptDbContextFiles)' != ''");
+ target.Task("Delete", task =>
+ {
+ task.Param("Files", "@(_EfcptConfigurationFiles)");
+ }, "'@(_EfcptConfigurationFiles)' != ''");
+ target.Message("Removed DbContext and configuration files from Models project", "normal", "'$(_EfcptHasFilesToCopy)' == 'true'");
+ });
+ t.Target( target =>
+ {
+ target.BeforeTargets("CoreCompile");
+ target.DependsOnTargets("EfcptResolveInputs;EfcptUseDirectDacpac;EfcptEnsureDacpac;EfcptStageInputs;EfcptComputeFingerprint;EfcptGenerateModels;EfcptCopyDataToDataProject");
+ target.Condition("'$(EfcptEnabled)' == 'true' and '$(_EfcptIsSqlProject)' != 'true'");
+ target.ItemGroup(null, group =>
+ {
+ group.Include("Compile", "$(EfcptGeneratedDir)Models\\**\\*.g.cs", null, "'$(EfcptSplitOutputs)' == 'true'");
+ group.Include("Compile", "$(EfcptGeneratedDir)**\\*.g.cs", null, "'$(EfcptSplitOutputs)' != 'true'");
+ });
+ });
+ t.Target( target =>
+ {
+ target.BeforeTargets("CoreCompile");
+ target.Condition("'$(EfcptExternalDataDir)' != '' and Exists('$(EfcptExternalDataDir)')");
+ target.ItemGroup(null, group =>
+ {
+ group.Include("Compile", "$(EfcptExternalDataDir)**\\*.g.cs");
+ });
+ target.Message("Including external data files from: $(EfcptExternalDataDir)", "normal");
+ });
+ t.Target( target =>
+ {
+ target.AfterTargets("Clean");
+ target.Condition("'$(EfcptEnabled)' == 'true'");
+ target.Message("Cleaning efcpt output: $(EfcptOutput)", "normal");
+ target.Task("RemoveDir", task =>
+ {
+ task.Param("Directories", "$(EfcptOutput)");
+ }, "Exists('$(EfcptOutput)')");
+ });
+ t.Target("_EfcptFinalizeProfiling", target =>
+ {
+ target.AfterTargets("Build");
+ target.Condition("'$(EfcptEnabled)' == 'true' and '$(EfcptEnableProfiling)' == 'true'");
+ target.Task("FinalizeBuildProfiling", task =>
+ {
+ task.Param("ProjectPath", "$(MSBuildProjectFullPath)");
+ task.Param("OutputPath", "$(EfcptProfilingOutput)");
+ task.Param("BuildSucceeded", "true");
+ });
+ });
+ })
+ .Build();
+ }
+
+ // Strongly-typed names
+ public readonly struct EfcptDacpacPath : IMsBuildPropertyName
+ {
+ public string Name => "_EfcptDacpacPath";
+ }
+ public readonly struct EfcptDatabaseName : IMsBuildPropertyName
+ {
+ public string Name => "_EfcptDatabaseName";
+ }
+ public readonly struct EfcptDataDestDir : IMsBuildPropertyName
+ {
+ public string Name => "_EfcptDataDestDir";
+ }
+ public readonly struct EfcptDataProjectDir : IMsBuildPropertyName
+ {
+ public string Name => "_EfcptDataProjectDir";
+ }
+ public readonly struct EfcptDataProjectPath : IMsBuildPropertyName
+ {
+ public string Name => "_EfcptDataProjectPath";
+ }
+ public readonly struct EfcptHasFilesToCopy : IMsBuildPropertyName
+ {
+ public string Name => "_EfcptHasFilesToCopy";
+ }
+ public readonly struct EfcptIsSqlProject : IMsBuildPropertyName
+ {
+ public string Name => "_EfcptIsSqlProject";
+ }
+ public readonly struct EfcptIsUsingDefaultConfig : IMsBuildPropertyName
+ {
+ public string Name => "_EfcptIsUsingDefaultConfig";
+ }
+ public readonly struct EfcptResolvedConfig : IMsBuildPropertyName
+ {
+ public string Name => "_EfcptResolvedConfig";
+ }
+ public readonly struct EfcptResolvedRenaming : IMsBuildPropertyName
+ {
+ public string Name => "_EfcptResolvedRenaming";
+ }
+ public readonly struct EfcptResolvedTemplateDir : IMsBuildPropertyName
+ {
+ public string Name => "_EfcptResolvedTemplateDir";
+ }
+ public readonly struct EfcptScriptsDir : IMsBuildPropertyName
+ {
+ public string Name => "_EfcptScriptsDir";
+ }
+ public readonly struct EfcptTaskAssembly : IMsBuildPropertyName
+ {
+ public string Name => "_EfcptTaskAssembly";
+ }
+ public readonly struct EfcptTasksFolder : IMsBuildPropertyName
+ {
+ public string Name => "_EfcptTasksFolder";
+ }
+ public readonly struct EfcptUseConnectionString : IMsBuildPropertyName
+ {
+ public string Name => "_EfcptUseConnectionString";
+ }
+ public readonly struct EfcptUseDirectDacpac : IMsBuildPropertyName
+ {
+ public string Name => "_EfcptUseDirectDacpac";
+ }
+ public readonly struct EfcptConfigDbContextName : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigDbContextName";
+ }
+ public readonly struct EfcptConfigUseNullableReferenceTypes : IMsBuildPropertyName
+ {
+ public string Name => "EfcptConfigUseNullableReferenceTypes";
+ }
+ // Item types:
+ public readonly struct EfcptConfigurationFilesItem : IMsBuildItemTypeName
+ {
+ public string Name => "_EfcptConfigurationFiles";
+ }
+ public readonly struct EfcptDbContextFilesItem : IMsBuildItemTypeName
+ {
+ public string Name => "_EfcptDbContextFiles";
+ }
+ public readonly struct EfcptGeneratedScriptsItem : IMsBuildItemTypeName
+ {
+ public string Name => "_EfcptGeneratedScripts";
+ }
+ public readonly struct CompileItem : IMsBuildItemTypeName
+ {
+ public string Name => "Compile";
+ }
+ public readonly struct EfcptCheckForUpdatesTarget : IMsBuildTargetName
+ {
+ public string Name => "_EfcptCheckForUpdates";
+ }
+ public readonly struct EfcptDetectSqlProjectTarget : IMsBuildTargetName
+ {
+ public string Name => "_EfcptDetectSqlProject";
+ }
+ public readonly struct EfcptFinalizeProfilingTarget : IMsBuildTargetName
+ {
+ public string Name => "_EfcptFinalizeProfiling";
+ }
+ public readonly struct EfcptInitializeProfilingTarget : IMsBuildTargetName
+ {
+ public string Name => "_EfcptInitializeProfiling";
+ }
+ public readonly struct EfcptLogTaskAssemblyInfoTarget : IMsBuildTargetName
+ {
+ public string Name => "_EfcptLogTaskAssemblyInfo";
+ }
+ public readonly struct AfterEfcptGenerationTarget : IMsBuildTargetName
+ {
+ public string Name => "AfterEfcptGeneration";
+ }
+ public readonly struct AfterSqlProjGenerationTarget : IMsBuildTargetName
+ {
+ public string Name => "AfterSqlProjGeneration";
+ }
+ public readonly struct BeforeEfcptGenerationTarget : IMsBuildTargetName
+ {
+ public string Name => "BeforeEfcptGeneration";
+ }
+ public readonly struct BeforeSqlProjGenerationTarget : IMsBuildTargetName
+ {
+ public string Name => "BeforeSqlProjGeneration";
+ }
+ public readonly struct EfcptAddSqlFileWarningsTarget : IMsBuildTargetName
+ {
+ public string Name => "EfcptAddSqlFileWarnings";
+ }
+ public readonly struct EfcptAddToCompileTarget : IMsBuildTargetName
+ {
+ public string Name => "EfcptAddToCompile";
+ }
+ public readonly struct EfcptApplyConfigOverridesTarget : IMsBuildTargetName
+ {
+ public string Name => "EfcptApplyConfigOverrides";
+ }
+ public readonly struct EfcptBuildSqlProjTarget : IMsBuildTargetName
+ {
+ public string Name => "EfcptBuildSqlProj";
+ }
+ public readonly struct EfcptCleanTarget : IMsBuildTargetName
+ {
+ public string Name => "EfcptClean";
+ }
+ public readonly struct EfcptComputeFingerprintTarget : IMsBuildTargetName
+ {
+ public string Name => "EfcptComputeFingerprint";
+ }
+ public readonly struct EfcptCopyDataToDataProjectTarget : IMsBuildTargetName
+ {
+ public string Name => "EfcptCopyDataToDataProject";
+ }
+ public readonly struct EfcptEnsureDacpacTarget : IMsBuildTargetName
+ {
+ public string Name => "EfcptEnsureDacpac";
+ }
+ public readonly struct EfcptExtractDatabaseSchemaToScriptsTarget : IMsBuildTargetName
+ {
+ public string Name => "EfcptExtractDatabaseSchemaToScripts";
+ }
+ public readonly struct EfcptGenerateModelsTarget : IMsBuildTargetName
+ {
+ public string Name => "EfcptGenerateModels";
+ }
+ public readonly struct EfcptIncludeExternalDataTarget : IMsBuildTargetName
+ {
+ public string Name => "EfcptIncludeExternalData";
+ }
+ public readonly struct EfcptQueryDatabaseSchemaForSqlProjTarget : IMsBuildTargetName
+ {
+ public string Name => "EfcptQueryDatabaseSchemaForSqlProj";
+ }
+ public readonly struct EfcptQuerySchemaMetadataTarget : IMsBuildTargetName
+ {
+ public string Name => "EfcptQuerySchemaMetadata";
+ }
+ public readonly struct EfcptResolveDbContextNameTarget : IMsBuildTargetName
+ {
+ public string Name => "EfcptResolveDbContextName";
+ }
+ public readonly struct EfcptResolveInputsTarget : IMsBuildTargetName
+ {
+ public string Name => "EfcptResolveInputs";
+ }
+ public readonly struct EfcptResolveInputsForDirectDacpacTarget : IMsBuildTargetName
+ {
+ public string Name => "EfcptResolveInputsForDirectDacpac";
+ }
+ public readonly struct EfcptSerializeConfigPropertiesTarget : IMsBuildTargetName
+ {
+ public string Name => "EfcptSerializeConfigProperties";
+ }
+ public readonly struct EfcptStageInputsTarget : IMsBuildTargetName
+ {
+ public string Name => "EfcptStageInputs";
+ }
+ public readonly struct EfcptUseDirectDacpacTarget : IMsBuildTargetName
+ {
+ public string Name => "EfcptUseDirectDacpac";
+ }
+ public readonly struct EfcptValidateSplitOutputsTarget : IMsBuildTargetName
+ {
+ public string Name => "EfcptValidateSplitOutputs";
+ }
+}
+
+
+
+
+
+
diff --git a/src/JD.Efcpt.Build.Definitions/Constants/Conditions.cs b/src/JD.Efcpt.Build.Definitions/Constants/Conditions.cs
new file mode 100644
index 0000000..e7d4649
--- /dev/null
+++ b/src/JD.Efcpt.Build.Definitions/Constants/Conditions.cs
@@ -0,0 +1,84 @@
+namespace JD.Efcpt.Build.Definitions.Constants;
+
+///
+/// Common MSBuild condition expressions used throughout the build definitions.
+/// Provides type-safe, reusable condition strings to eliminate duplication.
+///
+public static class Conditions
+{
+ ///
+ /// Checks if EFCPT is enabled for the project.
+ ///
+ public const string EfcptEnabled = "'$(EfcptEnabled)' == 'true'";
+
+ ///
+ /// Checks if the current project is a SQL database project.
+ ///
+ public const string IsSqlProject = "'$(_EfcptIsSqlProject)' == 'true'";
+
+ ///
+ /// Checks if the current project is NOT a SQL database project.
+ ///
+ public const string IsNotSqlProject = "'$(_EfcptIsSqlProject)' != 'true'";
+
+ ///
+ /// Checks if connection string mode is being used.
+ ///
+ public const string UseConnectionString = "'$(_EfcptUseConnectionString)' == 'true'";
+
+ ///
+ /// Checks if direct DACPAC mode is being used.
+ ///
+ public const string UseDirectDacpac = "'$(_EfcptUseDirectDacpac)' == 'true'";
+
+ ///
+ /// Checks if no DACPAC path is specified.
+ ///
+ public const string NoDacpac = "'$(EfcptDacpac)' == ''";
+
+ ///
+ /// Checks if split outputs mode is enabled.
+ ///
+ public const string SplitOutputs = "'$(EfcptSplitOutputs)' == 'true'";
+
+ ///
+ /// Checks if the EFCPT fingerprint has changed.
+ ///
+ public const string FingerprintChanged = "'$(_EfcptFingerprintChanged)' == 'true'";
+
+ ///
+ /// Combines multiple conditions with AND logic.
+ ///
+ /// The conditions to combine.
+ /// A combined condition string.
+ public static string And(params string[] conditions) =>
+ string.Join(" and ", conditions);
+
+ ///
+ /// Combines multiple conditions with OR logic.
+ ///
+ /// The conditions to combine.
+ /// A combined condition string.
+ public static string Or(params string[] conditions) =>
+ string.Join(" or ", conditions);
+
+ ///
+ /// Creates a condition that checks if EFCPT is enabled AND another condition is true.
+ ///
+ /// The additional condition.
+ /// A combined condition string.
+ public static string EfcptEnabledAnd(string condition) =>
+ And(EfcptEnabled, condition);
+
+ ///
+ /// Creates a condition for EFCPT-enabled SQL projects.
+ ///
+ public static string EfcptEnabledSqlProject =>
+ And(EfcptEnabled, IsSqlProject);
+
+ ///
+ /// Creates a condition for EFCPT-enabled data access projects (not SQL projects).
+ ///
+ public static string EfcptEnabledDataAccess =>
+ And(EfcptEnabled, IsNotSqlProject);
+}
diff --git a/src/JD.Efcpt.Build.Definitions/Constants/MSBuildVersions.cs b/src/JD.Efcpt.Build.Definitions/Constants/MSBuildVersions.cs
new file mode 100644
index 0000000..ddcfef7
--- /dev/null
+++ b/src/JD.Efcpt.Build.Definitions/Constants/MSBuildVersions.cs
@@ -0,0 +1,23 @@
+namespace JD.Efcpt.Build.Definitions.Constants;
+
+///
+/// MSBuild version constants for task assembly resolution.
+/// Maps MSBuild versions to Visual Studio releases.
+///
+public static class MSBuildVersions
+{
+ ///
+ /// MSBuild 18.0 - Visual Studio 2026 and later
+ ///
+ public const string VS2026 = "18.0";
+
+ ///
+ /// MSBuild 17.14 - Visual Studio 2024 Update 14 and later
+ ///
+ public const string VS2024Update14 = "17.14";
+
+ ///
+ /// MSBuild 17.12 - Visual Studio 2024 Update 12 and later
+ ///
+ public const string VS2024Update12 = "17.12";
+}
diff --git a/src/JD.Efcpt.Build.Definitions/DefinitionFactory.cs b/src/JD.Efcpt.Build.Definitions/DefinitionFactory.cs
new file mode 100644
index 0000000..8b321f4
--- /dev/null
+++ b/src/JD.Efcpt.Build.Definitions/DefinitionFactory.cs
@@ -0,0 +1,32 @@
+using JD.MSBuild.Fluent;
+
+namespace JD.Efcpt.Build.Definitions;
+
+///
+/// Main definition factory for JD.Efcpt.Build package.
+/// This factory coordinates all the build, buildTransitive, and SDK assets.
+///
+public static class DefinitionFactory
+{
+ public static PackageDefinition Create()
+ {
+ var buildProps = BuildPropsFactory.Create();
+ var buildTargets = BuildTargetsFactory.Create();
+ var buildTransitiveProps = BuildTransitivePropsFactory.Create();
+ var buildTransitiveTargets = BuildTransitiveTargetsFactory.Create();
+
+ return new PackageDefinition
+ {
+ Id = "JD.Efcpt.Build",
+ Description = "MSBuild tasks and targets for Entity Framework Core power tools",
+ BuildProps = buildProps.Props,
+ BuildTargets = buildTargets.Targets,
+ BuildTransitiveProps = buildTransitiveProps.Props,
+ BuildTransitiveTargets = buildTransitiveTargets.Targets,
+ Packaging =
+ {
+ BuildTransitive = true
+ }
+ };
+ }
+}
diff --git a/src/JD.Efcpt.Build.Definitions/JD.Efcpt.Build.Definitions.csproj b/src/JD.Efcpt.Build.Definitions/JD.Efcpt.Build.Definitions.csproj
new file mode 100644
index 0000000..e3b38da
--- /dev/null
+++ b/src/JD.Efcpt.Build.Definitions/JD.Efcpt.Build.Definitions.csproj
@@ -0,0 +1,35 @@
+
+
+
+ netstandard2.0
+ latest
+ enable
+ disable
+
+
+ JD.Efcpt.Build
+ JD.Efcpt.Build
+ MSBuild tasks and targets for Entity Framework Core power tools.
+ Jerrett Davis
+ Jerrett Davis
+ Copyright © Jerrett Davis
+ https://github.com/JerrettDavis/JD.Efcpt.Build
+ https://github.com/JerrettDavis/JD.Efcpt.Build
+ git
+ MIT
+ README.md
+ msbuild;efcore;ef-core;entity-framework;build-tools
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/JD.Efcpt.Build.Definitions/MsBuildNames.cs b/src/JD.Efcpt.Build.Definitions/MsBuildNames.cs
new file mode 100644
index 0000000..f3543dc
--- /dev/null
+++ b/src/JD.Efcpt.Build.Definitions/MsBuildNames.cs
@@ -0,0 +1,94 @@
+using JD.MSBuild.Fluent.Typed;
+
+namespace JD.Efcpt.Build.Definitions;
+
+///
+/// Strongly-typed MSBuild task names specific to JD.Efcpt.Build.
+/// For well-known MSBuild names, see .
+///
+public static class EfcptTaskNames
+{
+ // ====================================================================================
+ // JD.Efcpt.Build Tasks
+ // ====================================================================================
+
+ public readonly struct DetectSqlProjectTask : IMsBuildTaskName
+ {
+ public string Name => "DetectSqlProject";
+ }
+
+ public readonly struct ResolveSqlProjAndInputsTask : IMsBuildTaskName
+ {
+ public string Name => "ResolveSqlProjAndInputs";
+ }
+
+ public readonly struct EnsureDacpacBuiltTask : IMsBuildTaskName
+ {
+ public string Name => "EnsureDacpacBuilt";
+ }
+
+ public readonly struct StageEfcptInputsTask : IMsBuildTaskName
+ {
+ public string Name => "StageEfcptInputs";
+ }
+
+ public readonly struct ComputeFingerprintTask : IMsBuildTaskName
+ {
+ public string Name => "ComputeFingerprint";
+ }
+
+ public readonly struct RunEfcptTask : IMsBuildTaskName
+ {
+ public string Name => "RunEfcpt";
+ }
+
+ public readonly struct RenameGeneratedFilesTask : IMsBuildTaskName
+ {
+ public string Name => "RenameGeneratedFiles";
+ }
+
+ public readonly struct QuerySchemaMetadataTask : IMsBuildTaskName
+ {
+ public string Name => "QuerySchemaMetadata";
+ }
+
+ public readonly struct ApplyConfigOverridesTask : IMsBuildTaskName
+ {
+ public string Name => "ApplyConfigOverrides";
+ }
+
+ public readonly struct ResolveDbContextNameTask : IMsBuildTaskName
+ {
+ public string Name => "ResolveDbContextName";
+ }
+
+ public readonly struct SerializeConfigPropertiesTask : IMsBuildTaskName
+ {
+ public string Name => "SerializeConfigProperties";
+ }
+
+ public readonly struct CheckSdkVersionTask : IMsBuildTaskName
+ {
+ public string Name => "CheckSdkVersion";
+ }
+
+ public readonly struct RunSqlPackageTask : IMsBuildTaskName
+ {
+ public string Name => "RunSqlPackage";
+ }
+
+ public readonly struct AddSqlFileWarningsTask : IMsBuildTaskName
+ {
+ public string Name => "AddSqlFileWarnings";
+ }
+
+ public readonly struct InitializeBuildProfilingTask : IMsBuildTaskName
+ {
+ public string Name => "InitializeBuildProfiling";
+ }
+
+ public readonly struct FinalizeBuildProfilingTask : IMsBuildTaskName
+ {
+ public string Name => "FinalizeBuildProfiling";
+ }
+}
diff --git a/src/JD.Efcpt.Build.Definitions/Registry/UsingTasksRegistry.cs b/src/JD.Efcpt.Build.Definitions/Registry/UsingTasksRegistry.cs
new file mode 100644
index 0000000..aad498e
--- /dev/null
+++ b/src/JD.Efcpt.Build.Definitions/Registry/UsingTasksRegistry.cs
@@ -0,0 +1,48 @@
+using JD.MSBuild.Fluent.Common;
+using JD.MSBuild.Fluent.Fluent;
+
+namespace JD.Efcpt.Build.Definitions.Registry;
+
+///
+/// Centralized registry for all JD.Efcpt.Build custom MSBuild tasks.
+/// Automatically registers all task assemblies with MSBuild using a data-driven approach.
+///
+public static class UsingTasksRegistry
+{
+ ///
+ /// All custom task names in the JD.Efcpt.Build.Tasks assembly.
+ /// Adding a new task only requires adding its name to this array.
+ ///
+ private static readonly string[] TaskNames =
+ [
+ "AddSqlFileWarnings",
+ "ApplyConfigOverrides",
+ "CheckSdkVersion",
+ "ComputeFingerprint",
+ "DetectSqlProject",
+ "EnsureDacpacBuilt",
+ "FinalizeBuildProfiling",
+ "InitializeBuildProfiling",
+ "QuerySchemaMetadata",
+ "RenameGeneratedFiles",
+ "ResolveDbContextName",
+ "ResolveSqlProjAndInputs",
+ "RunEfcpt",
+ "RunSqlPackage",
+ "SerializeConfigProperties",
+ "StageEfcptInputs"
+ ];
+
+ ///
+ /// Registers all EFCPT custom tasks with MSBuild.
+ /// Uses the resolved task assembly path from SharedPropertyGroups.
+ ///
+ /// The targets builder to register tasks with.
+ public static void RegisterAll(TargetsBuilder t)
+ {
+ t.RegisterTasks(
+ assemblyPath: "$(_EfcptTaskAssembly)",
+ taskNamespace: "JD.Efcpt.Build.Tasks",
+ taskNames: TaskNames);
+ }
+}
diff --git a/src/JD.Efcpt.Build.Definitions/Shared/SharedPropertyGroups.cs b/src/JD.Efcpt.Build.Definitions/Shared/SharedPropertyGroups.cs
new file mode 100644
index 0000000..5a09715
--- /dev/null
+++ b/src/JD.Efcpt.Build.Definitions/Shared/SharedPropertyGroups.cs
@@ -0,0 +1,46 @@
+using JD.MSBuild.Fluent.Common;
+using JD.MSBuild.Fluent.Fluent;
+
+namespace JD.Efcpt.Build.Definitions.Shared;
+
+///
+/// Shared property group configurations used across both Props and Targets.
+/// Eliminates duplication and provides single source of truth.
+///
+public static class SharedPropertyGroups
+{
+ ///
+ /// Configures MSBuild property resolution for selecting the correct task assembly
+ /// based on MSBuild runtime version and type.
+ ///
+ public static void ConfigureTaskAssemblyResolution(PropsGroupBuilder group)
+ {
+ group.ResolveMultiTargetedTaskAssembly(
+ folderProperty: "_EfcptTasksFolder",
+ assemblyProperty: "_EfcptTaskAssembly",
+ assemblyFileName: "JD.Efcpt.Build.Tasks.dll",
+ nugetTasksPath: "$(MSBuildThisFileDirectory)..\\tasks",
+ localProjectPath: "$(MSBuildThisFileDirectory)..\\..\\JD.Efcpt.Build.Tasks");
+ }
+
+ ///
+ /// Configures EfcptConfigUseNullableReferenceTypes property based on project's Nullable setting.
+ /// Provides zero-config experience by deriving EFCPT settings from standard project settings.
+ ///
+ ///
+ /// Logic:
+ ///
+ /// - If Nullable is "enable" or "Enable" → set to true
+ /// - If Nullable has any other value → set to false
+ /// - If Nullable is not set → leave EfcptConfigUseNullableReferenceTypes as-is (user override)
+ ///
+ ///
+ public static void ConfigureNullableReferenceTypes(PropsGroupBuilder group)
+ {
+ group.Property("true",
+ "'$(EfcptConfigUseNullableReferenceTypes)'=='' and ('$(Nullable)'=='enable' or '$(Nullable)'=='Enable')");
+
+ group.Property("false",
+ "'$(EfcptConfigUseNullableReferenceTypes)'=='' and '$(Nullable)'!=''");
+ }
+}
diff --git a/src/JD.Efcpt.Build.Tasks/Chains/ConnectionStringResolutionChain.cs b/src/JD.Efcpt.Build.Tasks/Chains/ConnectionStringResolutionChain.cs
index ba97f1f..74dcf62 100644
--- a/src/JD.Efcpt.Build.Tasks/Chains/ConnectionStringResolutionChain.cs
+++ b/src/JD.Efcpt.Build.Tasks/Chains/ConnectionStringResolutionChain.cs
@@ -131,7 +131,7 @@ private static bool HasAppConfigFiles(string projectDirectory)
var fullPath = PathUtils.FullPath(explicitPath, projectDirectory);
var validator = new ConfigurationFileTypeValidator();
- validator.ValidateAndWarn(fullPath, propertyName, log);
+ ConfigurationFileTypeValidator.ValidateAndWarn(fullPath, propertyName, log);
var result = ParseConnectionStringFromFile(fullPath, connectionStringName, log);
return result.Success ? result.ConnectionString : null;
@@ -158,7 +158,7 @@ private static bool HasAppConfigFiles(string projectDirectory)
foreach (var file in appSettingsFiles.OrderBy(f => f == Path.Combine(projectDirectory, "appsettings.json") ? 0 : 1))
{
var parser = new AppSettingsConnectionStringParser();
- var result = parser.Parse(file, connectionStringName, log);
+ var result = AppSettingsConnectionStringParser.Parse(file, connectionStringName, log);
if (!result.Success || string.IsNullOrWhiteSpace(result.ConnectionString))
continue;
@@ -186,7 +186,7 @@ private static bool HasAppConfigFiles(string projectDirectory)
continue;
var parser = new AppConfigConnectionStringParser();
- var result = parser.Parse(path, connectionStringName, log);
+ var result = AppConfigConnectionStringParser.Parse(path, connectionStringName, log);
if (result.Success && !string.IsNullOrWhiteSpace(result.ConnectionString))
{
log.Detail($"Resolved connection string from auto-discovered file: {configFile}");
@@ -205,8 +205,8 @@ private static ConnectionStringResult ParseConnectionStringFromFile(
var ext = Path.GetExtension(filePath).ToLowerInvariant();
return ext switch
{
- ".json" => new AppSettingsConnectionStringParser().Parse(filePath, connectionStringName, log),
- ".config" => new AppConfigConnectionStringParser().Parse(filePath, connectionStringName, log),
+ ".json" => AppSettingsConnectionStringParser.Parse(filePath, connectionStringName, log),
+ ".config" => AppConfigConnectionStringParser.Parse(filePath, connectionStringName, log),
_ => ConnectionStringResult.Failed()
};
}
diff --git a/src/JD.Efcpt.Build.Tasks/Config/EfcptConfigGenerator.cs b/src/JD.Efcpt.Build.Tasks/Config/EfcptConfigGenerator.cs
index 061b2ce..b098a7e 100644
--- a/src/JD.Efcpt.Build.Tasks/Config/EfcptConfigGenerator.cs
+++ b/src/JD.Efcpt.Build.Tasks/Config/EfcptConfigGenerator.cs
@@ -17,6 +17,12 @@ public static class EfcptConfigGenerator
private const string PrimarySchemaUrl = "https://raw.githubusercontent.com/ErikEJ/EFCorePowerTools/master/samples/efcpt-config.schema.json";
private const string FallbackSchemaUrl = "https://raw.githubusercontent.com/JerrettDavis/JD.Efcpt.Build/refs/heads/main/lib/efcpt-config.schema.json";
+ private static readonly JsonSerializerOptions JsonOptions = new()
+ {
+ WriteIndented = true,
+ Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
+ };
+
///
/// Generates a default efcpt-config.json from a schema URL.
///
@@ -109,13 +115,7 @@ public static string GenerateFromSchema(
// Don't process TypeMappings as it's not required
// Serialize with indentation
- var options = new JsonSerializerOptions
- {
- WriteIndented = true,
- Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
- };
-
- return JsonSerializer.Serialize(config, options);
+ return JsonSerializer.Serialize(config, JsonOptions);
}
private static void ProcessCodeGeneration(JsonObject config, JsonObject definitions)
diff --git a/src/JD.Efcpt.Build.Tasks/ConnectionStrings/AppConfigConnectionStringParser.cs b/src/JD.Efcpt.Build.Tasks/ConnectionStrings/AppConfigConnectionStringParser.cs
index d9623c1..b8636d2 100644
--- a/src/JD.Efcpt.Build.Tasks/ConnectionStrings/AppConfigConnectionStringParser.cs
+++ b/src/JD.Efcpt.Build.Tasks/ConnectionStrings/AppConfigConnectionStringParser.cs
@@ -16,7 +16,7 @@ internal sealed class AppConfigConnectionStringParser
/// The name of the connection string to retrieve.
/// The build log for warnings and errors.
/// A result indicating success or failure, along with the connection string if found.
- public ConnectionStringResult Parse(string filePath, string connectionStringName, BuildLog log)
+ public static ConnectionStringResult Parse(string filePath, string connectionStringName, BuildLog log)
{
try
{
@@ -40,7 +40,7 @@ public ConnectionStringResult Parse(string filePath, string connectionStringName
return ConnectionStringResult.WithSuccess(match.ConnectionString!, filePath, match.Name!);
// Fallback to first available
- if (connectionStrings.Any())
+ if (connectionStrings.Count > 0)
{
var first = connectionStrings.First();
log.Warn("JD0002",
diff --git a/src/JD.Efcpt.Build.Tasks/ConnectionStrings/AppSettingsConnectionStringParser.cs b/src/JD.Efcpt.Build.Tasks/ConnectionStrings/AppSettingsConnectionStringParser.cs
index 3f25168..75a7921 100644
--- a/src/JD.Efcpt.Build.Tasks/ConnectionStrings/AppSettingsConnectionStringParser.cs
+++ b/src/JD.Efcpt.Build.Tasks/ConnectionStrings/AppSettingsConnectionStringParser.cs
@@ -14,7 +14,7 @@ internal sealed class AppSettingsConnectionStringParser
/// The name of the connection string to retrieve.
/// The build log for warnings and errors.
/// A result indicating success or failure, along with the connection string if found.
- public ConnectionStringResult Parse(string filePath, string connectionStringName, BuildLog log)
+ public static ConnectionStringResult Parse(string filePath, string connectionStringName, BuildLog log)
{
try
{
diff --git a/src/JD.Efcpt.Build.Tasks/ConnectionStrings/ConfigurationFileTypeValidator.cs b/src/JD.Efcpt.Build.Tasks/ConnectionStrings/ConfigurationFileTypeValidator.cs
index 8f43c98..527780d 100644
--- a/src/JD.Efcpt.Build.Tasks/ConnectionStrings/ConfigurationFileTypeValidator.cs
+++ b/src/JD.Efcpt.Build.Tasks/ConnectionStrings/ConfigurationFileTypeValidator.cs
@@ -11,7 +11,7 @@ internal sealed class ConfigurationFileTypeValidator
/// The path to the configuration file.
/// The name of the parameter (e.g., "EfcptAppSettings" or "EfcptAppConfig").
/// The build log for warnings.
- public void ValidateAndWarn(string filePath, string parameterName, BuildLog log)
+ public static void ValidateAndWarn(string filePath, string parameterName, BuildLog log)
{
var extension = Path.GetExtension(filePath).ToLowerInvariant();
var isJson = extension == ".json";
diff --git a/src/JD.Efcpt.Build.Tasks/DbContextNameGenerator.cs b/src/JD.Efcpt.Build.Tasks/DbContextNameGenerator.cs
index daf70e1..60899dd 100644
--- a/src/JD.Efcpt.Build.Tasks/DbContextNameGenerator.cs
+++ b/src/JD.Efcpt.Build.Tasks/DbContextNameGenerator.cs
@@ -33,6 +33,8 @@ public static class DbContextNameGenerator
{
private const string DefaultContextName = "MyDbContext";
private const string ContextSuffix = "Context";
+
+ private static readonly char[] DotSeparator = ['.'];
///
/// Generates a DbContext name from the provided SQL project path.
@@ -209,7 +211,7 @@ private static string HumanizeName(string rawName)
return DefaultContextName;
// Handle dotted namespaces (e.g., "Org.Unit.SystemData" → "SystemData")
- var dotParts = rawName.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
+ var dotParts = rawName.Split(DotSeparator, StringSplitOptions.RemoveEmptyEntries);
var baseName = dotParts.Length > 0 ? dotParts[^1] : rawName;
// Remove digits at the end (common in DACPAC names like "MyDb20251225.dacpac")
diff --git a/src/JD.Efcpt.Build.Tasks/DetectSqlProject.cs b/src/JD.Efcpt.Build.Tasks/DetectSqlProject.cs
index f86668b..46c20db 100644
--- a/src/JD.Efcpt.Build.Tasks/DetectSqlProject.cs
+++ b/src/JD.Efcpt.Build.Tasks/DetectSqlProject.cs
@@ -61,7 +61,7 @@ private bool ExecuteCore(TaskExecutionContext ctx)
}
// Fall back to property-based detection for legacy SSDT projects
- var hasLegacyProperties = !string.IsNullOrEmpty(SqlServerVersion) || !string.IsNullOrEmpty(DSP);
+ var hasLegacyProperties = !string.IsNullOrWhiteSpace(SqlServerVersion) || !string.IsNullOrWhiteSpace(DSP);
if (hasLegacyProperties)
{
diff --git a/src/JD.Efcpt.Build.Tasks/Profiling/BuildProfiler.cs b/src/JD.Efcpt.Build.Tasks/Profiling/BuildProfiler.cs
index b6034df..7821986 100644
--- a/src/JD.Efcpt.Build.Tasks/Profiling/BuildProfiler.cs
+++ b/src/JD.Efcpt.Build.Tasks/Profiling/BuildProfiler.cs
@@ -27,6 +27,11 @@ public interface ITaskTracker : IDisposable
public sealed class BuildProfiler
{
private static readonly BuildRunOutput EmptyRunOutput = new();
+ private static readonly JsonSerializerOptions JsonOptions = new()
+ {
+ WriteIndented = true,
+ DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull
+ };
private readonly BuildRunOutput _runOutput;
private readonly Stack _nodeStack = new();
@@ -238,13 +243,7 @@ public void Complete(string outputPath)
}
// Write profile to file with indented JSON for human readability
- var options = new JsonSerializerOptions
- {
- WriteIndented = true,
- DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull
- };
-
- var json = JsonSerializer.Serialize(_runOutput, options);
+ var json = JsonSerializer.Serialize(_runOutput, JsonOptions);
File.WriteAllText(outputPath, json);
}
}
diff --git a/src/JD.Efcpt.Build.Tasks/RunEfcpt.cs b/src/JD.Efcpt.Build.Tasks/RunEfcpt.cs
index 37ad3fe..d362302 100644
--- a/src/JD.Efcpt.Build.Tasks/RunEfcpt.cs
+++ b/src/JD.Efcpt.Build.Tasks/RunEfcpt.cs
@@ -82,6 +82,8 @@ public sealed class RunEfcpt : Task
///
private const int ProcessTimeoutMs = 5000;
+ private static readonly string[] NewLineSeparators = ["\r\n", "\n"];
+
///
/// Controls how the efcpt dotnet tool is resolved.
///
@@ -546,7 +548,7 @@ private static bool IsDotNet10SdkInstalled(string dotnetExe)
// Parse output like "10.0.100 [C:\Program Files\dotnet\sdk]"
// Check if any line starts with "10." or higher
- foreach (var line in output.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries))
+ foreach (var line in output.Split(NewLineSeparators, StringSplitOptions.RemoveEmptyEntries))
{
var trimmed = line.Trim();
if (string.IsNullOrEmpty(trimmed))
diff --git a/src/JD.Efcpt.Build.Tasks/RunSqlPackage.cs b/src/JD.Efcpt.Build.Tasks/RunSqlPackage.cs
index 277280a..0e7ddc3 100644
--- a/src/JD.Efcpt.Build.Tasks/RunSqlPackage.cs
+++ b/src/JD.Efcpt.Build.Tasks/RunSqlPackage.cs
@@ -182,7 +182,7 @@ private bool ExecuteCore(TaskExecutionContext ctx)
if (Directory.Exists(dacpacTempDir))
{
log.Detail($"Moving extracted files from {dacpacTempDir} to {TargetDirectory}");
- MoveDirectoryContents(dacpacTempDir, TargetDirectory, log);
+ RunSqlPackage.MoveDirectoryContents(dacpacTempDir, TargetDirectory, log);
// Clean up temp directory
try
@@ -428,7 +428,7 @@ private bool ExecuteSqlPackage((string Executable, string Arguments) toolInfo, s
///
/// Recursively moves all contents from source directory to destination directory.
///
- private void MoveDirectoryContents(string sourceDir, string destDir, IBuildLog log)
+ private static void MoveDirectoryContents(string sourceDir, string destDir, IBuildLog log)
{
// Ensure source directory path ends with separator for proper substring
var sourceDirNormalized = sourceDir.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + Path.DirectorySeparatorChar;
diff --git a/src/JD.Efcpt.Build.Tasks/SqlProjectDetector.cs b/src/JD.Efcpt.Build.Tasks/SqlProjectDetector.cs
index 0bbb2f1..1bc8302 100644
--- a/src/JD.Efcpt.Build.Tasks/SqlProjectDetector.cs
+++ b/src/JD.Efcpt.Build.Tasks/SqlProjectDetector.cs
@@ -9,6 +9,8 @@ internal static class SqlProjectDetector
["Microsoft.Build.Sql", "MSBuild.Sdk.SqlProj"],
StringComparer.OrdinalIgnoreCase);
+ private static readonly char[] SemicolonSeparator = [';'];
+
public static bool IsSqlProjectReference(string projectPath)
{
if (string.IsNullOrWhiteSpace(projectPath))
@@ -79,7 +81,7 @@ private static bool HasSupportedSdkAttribute(XElement project)
private static IEnumerable ParseSdkNames(string raw)
=> raw
- .Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
+ .Split(SemicolonSeparator, StringSplitOptions.RemoveEmptyEntries)
.Select(entry => entry.Trim())
.Where(entry => entry.Length > 0)
.Select(entry =>
diff --git a/src/JD.Efcpt.Build.Tasks/Utilities/DotNetToolUtilities.cs b/src/JD.Efcpt.Build.Tasks/Utilities/DotNetToolUtilities.cs
index 4546e03..2d60521 100644
--- a/src/JD.Efcpt.Build.Tasks/Utilities/DotNetToolUtilities.cs
+++ b/src/JD.Efcpt.Build.Tasks/Utilities/DotNetToolUtilities.cs
@@ -13,6 +13,9 @@ internal static class DotNetToolUtilities
///
private const int ProcessTimeoutMs = 5000;
+ private static readonly char[] NewLineSeparator = ['\n'];
+ private static readonly char[] SpaceSeparator = [' ', '\t'];
+
///
/// Checks if the .NET 10.0 (or later) SDK is installed by running `dotnet --list-sdks`.
///
@@ -61,7 +64,7 @@ public static bool IsDotNet10SdkInstalled(string dotnetExe)
var output = outputBuilder.ToString();
// Parse SDK versions from output like "10.0.100 [C:\Program Files\dotnet\sdk]"
- foreach (var line in output.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries))
+ foreach (var line in output.Split(NewLineSeparator, StringSplitOptions.RemoveEmptyEntries))
{
var trimmed = line.Trim();
var firstSpace = trimmed.IndexOf(' ');
@@ -131,14 +134,14 @@ public static bool IsDnxAvailable(string dotnetExe)
var output = outputBuilder.ToString();
// If we can list runtimes and at least one .NET 10 runtime is present, dnx is available
- foreach (var line in output.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries))
+ foreach (var line in output.Split(NewLineSeparator, StringSplitOptions.RemoveEmptyEntries))
{
var trimmed = line.Trim();
if (string.IsNullOrEmpty(trimmed))
continue;
// Expected format: " [path]"
- var parts = trimmed.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
+ var parts = trimmed.Split(SpaceSeparator, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length < 2)
continue;
diff --git a/src/JD.Efcpt.Build.Tasks/packages.lock.json b/src/JD.Efcpt.Build.Tasks/packages.lock.json
index 33b9d54..0589cde 100644
--- a/src/JD.Efcpt.Build.Tasks/packages.lock.json
+++ b/src/JD.Efcpt.Build.Tasks/packages.lock.json
@@ -84,15 +84,6 @@
"SQLitePCLRaw.core": "2.1.10"
}
},
- "Microsoft.NETFramework.ReferenceAssemblies": {
- "type": "Direct",
- "requested": "[1.0.3, )",
- "resolved": "1.0.3",
- "contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
- "dependencies": {
- "Microsoft.NETFramework.ReferenceAssemblies.net472": "1.0.3"
- }
- },
"MySqlConnector": {
"type": "Direct",
"requested": "[2.4.0, )",
@@ -504,11 +495,6 @@
"System.Runtime.CompilerServices.Unsafe": "6.1.0"
}
},
- "Microsoft.NETFramework.ReferenceAssemblies.net472": {
- "type": "Transitive",
- "resolved": "1.0.3",
- "contentHash": "0E7evZXHXaDYYiLRfpyXvCh+yzM2rNTyuZDI+ZO7UUqSc6GfjePiXTdqJGtgIKUwdI81tzQKmaWprnUiPj9hAw=="
- },
"Mono.Unix": {
"type": "Transitive",
"resolved": "7.1.0-final.1.21458.1",
diff --git a/src/JD.Efcpt.Build.Templates/packages.lock.json b/src/JD.Efcpt.Build.Templates/packages.lock.json
new file mode 100644
index 0000000..b7e843e
--- /dev/null
+++ b/src/JD.Efcpt.Build.Templates/packages.lock.json
@@ -0,0 +1,21 @@
+{
+ "version": 1,
+ "dependencies": {
+ ".NETStandard,Version=v2.0": {
+ "NETStandard.Library": {
+ "type": "Direct",
+ "requested": "[2.0.3, )",
+ "resolved": "2.0.3",
+ "contentHash": "st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0"
+ }
+ },
+ "Microsoft.NETCore.Platforms": {
+ "type": "Transitive",
+ "resolved": "1.1.0",
+ "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A=="
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/JD.Efcpt.Build/GENERATING.md b/src/JD.Efcpt.Build/GENERATING.md
new file mode 100644
index 0000000..955d522
--- /dev/null
+++ b/src/JD.Efcpt.Build/GENERATING.md
@@ -0,0 +1,88 @@
+# Regenerating MSBuild Files
+
+The `buildTransitive/` MSBuild files (`.props` and `.targets`) are generated from C# definitions using [JD.MSBuild.Fluent](https://www.nuget.org/packages/JD.MSBuild.Fluent).
+
+## Why Generation is Disabled
+
+Automatic generation is **disabled by default** due to a file locking issue when multi-targeting:
+
+1. JD.MSBuild.Fluent loads `JD.Efcpt.Build.dll` to call `DefinitionFactory.Create()`
+2. The loaded DLL is locked by the .NET host process
+3. MSBuild tries to copy the DLL to `bin/` but fails because it's locked
+4. Build fails after 10 retries
+
+This affects both local builds and CI.
+
+## When to Regenerate
+
+Regenerate the MSBuild files when you modify:
+
+- `Definitions/BuildTransitivePropsFactory.cs`
+- `Definitions/BuildTransitiveTargetsFactory.cs`
+- `Definitions/Registry/UsingTasksRegistry.cs`
+- `Definitions/Shared/SharedPropertyGroups.cs`
+
+## How to Regenerate
+
+### Option 1: Single Target Framework (Recommended)
+
+Build only `net8.0` to avoid multi-targeting file locks:
+
+```powershell
+cd src/JD.Efcpt.Build
+dotnet msbuild -t:JDMSBuildFluentGenerate -p:TargetFramework=net8.0 -p:JDMSBuildFluentGenerateEnabled=true
+```
+
+This generates files to `obj/msbuild_fluent_generated/` which are then copied to `buildTransitive/`.
+
+### Option 2: Enable in Project File
+
+Temporarily enable generation in `JD.Efcpt.Build.csproj`:
+
+```xml
+true
+```
+
+Then build:
+
+```powershell
+dotnet build -p:TargetFramework=net8.0
+```
+
+**Warning:** Don't commit with generation enabled, or CI will fail!
+
+### Option 3: Clean Rebuild
+
+If you don't have stale processes locking files:
+
+```powershell
+dotnet clean
+dotnet build -p:TargetFramework=net8.0 -p:JDMSBuildFluentGenerateEnabled=true
+```
+
+## Verifying Generated Files
+
+After regeneration, check that these files exist and are updated:
+
+```
+buildTransitive/
+├── JD.Efcpt.Build.props
+└── JD.Efcpt.Build.targets
+```
+
+Commit the regenerated files:
+
+```powershell
+git add buildTransitive/
+git commit -m "chore: regenerate MSBuild files from definitions"
+```
+
+## CI Considerations
+
+CI always has `JDMSBuildFluentGenerateEnabled=false` because:
+
+1. Generated files are tracked in git (source of truth)
+2. Multi-targeting causes file locking failures
+3. Faster CI builds (no generation overhead)
+
+The generated files should be reviewed in PRs like any other code.
diff --git a/src/JD.Efcpt.Build/JD.Efcpt.Build.csproj b/src/JD.Efcpt.Build/JD.Efcpt.Build.csproj
index 4c1c6b7..1e52a96 100644
--- a/src/JD.Efcpt.Build/JD.Efcpt.Build.csproj
+++ b/src/JD.Efcpt.Build/JD.Efcpt.Build.csproj
@@ -4,11 +4,14 @@
net8.0;net9.0;net10.0
true
+
+ false
+
JD.Efcpt.Build
Jerrett Davis
JDH Productions
-
+
MSBuild Integration for EF Core Power Tools
Enterprise-grade MSBuild integration for EF Core Power Tools CLI. Automate database-first EF Core model generation as part of your build pipeline. Zero manual steps, full CI/CD support, reproducible builds. Automatically builds your SQL Server Database Project (.sqlproj) to a DACPAC, runs efcpt, and generates DbContext and entity classes during dotnet build.
@@ -19,19 +22,29 @@
README.md
MIT
false
-
+
false
true
$(NoWarn);NU5128;NU5100
false
+
+
+ <_JDMSBuildFluentDirectReference>true
+
+ false
+ JD.Efcpt.Build.Definitions.DefinitionFactory
+ Create
+
+
+
+ IncludeAssets="Compile" />
-
-
+
+
+
+
@@ -90,3 +107,5 @@
+
+
diff --git a/src/JD.Efcpt.Build/JD.Efcpt.Build.props b/src/JD.Efcpt.Build/JD.Efcpt.Build.props
new file mode 100644
index 0000000..f5ae7b8
--- /dev/null
+++ b/src/JD.Efcpt.Build/JD.Efcpt.Build.props
@@ -0,0 +1,15 @@
+
+
+
+
+ <_EfcptIsDirectReference>true
+
+
+
+
+
diff --git a/src/JD.Efcpt.Build/JD.Efcpt.Build.targets b/src/JD.Efcpt.Build/JD.Efcpt.Build.targets
new file mode 100644
index 0000000..6a24d21
--- /dev/null
+++ b/src/JD.Efcpt.Build/JD.Efcpt.Build.targets
@@ -0,0 +1,9 @@
+
+
+
+
+
+
diff --git a/src/JD.Efcpt.Build/buildTransitive/JD.Efcpt.Build.props b/src/JD.Efcpt.Build/buildTransitive/JD.Efcpt.Build.props
index 7f7c97a..a7e08b8 100644
--- a/src/JD.Efcpt.Build/buildTransitive/JD.Efcpt.Build.props
+++ b/src/JD.Efcpt.Build/buildTransitive/JD.Efcpt.Build.props
@@ -1,7 +1,7 @@
-
+
+
-
- true
-
-
- $(BaseIntermediateOutputPath)efcpt\
- $(EfcptOutput)Generated\
-
-
-
-
- efcpt-config.json
- efcpt.renaming.json
- Template
-
-
-
-
-
- DefaultConnection
-
- mssql
-
-
- $(SolutionDir)
- $(SolutionPath)
- true
-
-
- auto
- ErikEJ.EFCorePowerTools.Cli
- 10.*
- true
- efcpt
-
- dotnet
-
-
- $(EfcptOutput)fingerprint.txt
- $(EfcptOutput).efcpt.stamp
- false
-
-
- minimal
- false
-
-
+ true
+
+ $(BaseIntermediateOutputPath)efcpt\
+ $(EfcptOutput)Generated\
+
+
+
+ efcpt-config.json
+ efcpt.renaming.json
+ Template
+
+
+
+
+ DefaultConnection
+
+ mssql
+
+ $(SolutionDir)
+ $(SolutionPath)
+ true
+
+ auto
+ ErikEJ.EFCorePowerTools.Cli
+ 10.*
+ true
+ efcpt
+
+ dotnet
+
+ $(EfcptOutput)fingerprint.txt
+ $(EfcptOutput).efcpt.stamp
+ false
+
+ minimal
+ false
+
- Info
- Warn
-
-
+ Info
+ Warn
+
- false
- 24
- false
-
-
+ false
+ 24
+ false
+
- false
-
- obj\efcpt\Generated\
-
-
-
-
-
+ false
+
+ obj\efcpt\Generated\
+
+
+
- true
-
-
-
- $(RootNamespace)
- $(MSBuildProjectName)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ true
+
+
+ $(RootNamespace)
+ $(MSBuildProjectName)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- false
- $(EfcptOutput)build-profile.json
- minimal
+ (values: "minimal", "detailed"; default: "minimal")-->
+ false
+ $(EfcptOutput)build-profile.json
+ minimal
-
-
- microsoft-build-sql
- csharp
- $(MSBuildProjectDirectory)\
- $(MSBuildProjectDirectory)\
- Sql160
-
- true
-
+
+ microsoft-build-sql
+ csharp
+ $(MSBuildProjectDirectory)\
+ $(MSBuildProjectDirectory)\
+ Sql160
+
+ true
+
diff --git a/src/JD.Efcpt.Build/buildTransitive/JD.Efcpt.Build.targets b/src/JD.Efcpt.Build/buildTransitive/JD.Efcpt.Build.targets
index 8ddc286..f08aaea 100644
--- a/src/JD.Efcpt.Build/buildTransitive/JD.Efcpt.Build.targets
+++ b/src/JD.Efcpt.Build/buildTransitive/JD.Efcpt.Build.targets
@@ -1,81 +1,33 @@
-
-
-
+
+
+
-
- true
- false
+
+ true
+ false
-
-
+
-
+
-
-
-
- <_EfcptIsSqlProject Condition="'$(_EfcptIsSqlProject)'==''">false
+
+ <_EfcptIsSqlProject>false
-
-
+
-
<_EfcptTasksFolder Condition="'$(MSBuildRuntimeType)' == 'Core' and $([MSBuild]::VersionGreaterThanOrEquals('$(MSBuildVersion)', '18.0'))">net10.0
- <_EfcptTasksFolder Condition="'$(_EfcptTasksFolder)' == '' and '$(MSBuildRuntimeType)' == 'Core' and $([MSBuild]::VersionGreaterThanOrEquals('$(MSBuildVersion)', '17.14'))">net10.0
- <_EfcptTasksFolder Condition="'$(_EfcptTasksFolder)' == '' and '$(MSBuildRuntimeType)' == 'Core' and $([MSBuild]::VersionGreaterThanOrEquals('$(MSBuildVersion)', '17.12'))">net9.0
- <_EfcptTasksFolder Condition="'$(_EfcptTasksFolder)' == '' and '$(MSBuildRuntimeType)' == 'Core'">net8.0
-
-
+ <_EfcptTasksFolder Condition="('$(_EfcptTasksFolder)' == '') and ('$(MSBuildRuntimeType)' == 'Core' and $([MSBuild]::VersionGreaterThanOrEquals('$(MSBuildVersion)', '17.14')))">net10.0
+ <_EfcptTasksFolder Condition="('$(_EfcptTasksFolder)' == '') and ('$(MSBuildRuntimeType)' == 'Core' and $([MSBuild]::VersionGreaterThanOrEquals('$(MSBuildVersion)', '17.12')))">net9.0
+ <_EfcptTasksFolder Condition="('$(_EfcptTasksFolder)' == '') and ('$(MSBuildRuntimeType)' == 'Core')">net8.0
<_EfcptTasksFolder Condition="'$(_EfcptTasksFolder)' == ''">net472
-
-
- <_EfcptTaskAssembly>$(MSBuildThisFileDirectory)..\tasks\$(_EfcptTasksFolder)\JD.Efcpt.Build.Tasks.dll
-
-
- <_EfcptTaskAssembly Condition="!Exists('$(_EfcptTaskAssembly)')">$(MSBuildThisFileDirectory)..\..\JD.Efcpt.Build.Tasks\bin\$(Configuration)\$(_EfcptTasksFolder)\JD.Efcpt.Build.Tasks.dll
- <_EfcptTaskAssembly Condition="!Exists('$(_EfcptTaskAssembly)') and '$(Configuration)' == ''">$(MSBuildThisFileDirectory)..\..\JD.Efcpt.Build.Tasks\bin\Debug\$(_EfcptTasksFolder)\JD.Efcpt.Build.Tasks.dll
+ <_EfcptTaskAssembly>$(MSBuildThisFileDirectory)\..\tasks\$(_EfcptTasksFolder)\JD.Efcpt.Build.Tasks.dll
+ <_EfcptTaskAssembly Condition="!Exists('$(_EfcptTaskAssembly)')">$(MSBuildThisFileDirectory)\..\..\JD.Efcpt.Build.Tasks\bin\$(Configuration)\$(_EfcptTasksFolder)\JD.Efcpt.Build.Tasks.dll
+ <_EfcptTaskAssembly Condition="(!Exists('$(_EfcptTaskAssembly)')) and ('$(Configuration)' == '')">$(MSBuildThisFileDirectory)\..\..\JD.Efcpt.Build.Tasks\bin\Debug\$(_EfcptTasksFolder)\JD.Efcpt.Build.Tasks.dll
-
-
-
+
+
@@ -83,232 +35,83 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+
-
-
-
-
+
+
-
<_EfcptScriptsDir>$(EfcptSqlScriptsDir)
-
-
-
-
<_EfcptGeneratedScripts Include="$(_EfcptScriptsDir)**\*.sql" />
-
-
-
+
+
-
-
-
-
-
-
-
+
+
+
- <_EfcptDatabaseName Condition="$(EfcptConnectionString.Contains('Database='))">$([System.Text.RegularExpressions.Regex]::Match($(EfcptConnectionString), 'Database\s*=\s*\"?([^;"]+)\"?').Groups[1].Value)
- <_EfcptDatabaseName Condition="$(EfcptConnectionString.Contains('Initial Catalog='))">$([System.Text.RegularExpressions.Regex]::Match($(EfcptConnectionString), 'Initial Catalog\s*=\s*\"?([^;"]+)\"?').Groups[1].Value)
+ <_EfcptDatabaseName>$([System.Text.RegularExpressions.Regex]::Match($(EfcptConnectionString), 'Database\s*=\s*\"?([^;"]+)\"?').Groups[1].Value)
+ <_EfcptDatabaseName>$([System.Text.RegularExpressions.Regex]::Match($(EfcptConnectionString), 'Initial Catalog\s*=\s*\"?([^;"]+)\"?').Groups[1].Value)
-
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
@@ -318,457 +121,150 @@
-
-
-
+
+
- <_EfcptResolvedConfig Condition="Exists('$(MSBuildProjectDirectory)\$(EfcptConfig)')">$(MSBuildProjectDirectory)\$(EfcptConfig)
- <_EfcptResolvedConfig Condition="'$(_EfcptResolvedConfig)' == ''">$(MSBuildThisFileDirectory)Defaults\efcpt-config.json
- <_EfcptResolvedRenaming Condition="Exists('$(MSBuildProjectDirectory)\$(EfcptRenaming)')">$(MSBuildProjectDirectory)\$(EfcptRenaming)
- <_EfcptResolvedRenaming Condition="'$(_EfcptResolvedRenaming)' == ''">$(MSBuildThisFileDirectory)Defaults\efcpt.renaming.json
- <_EfcptResolvedTemplateDir Condition="Exists('$(MSBuildProjectDirectory)\$(EfcptTemplateDir)')">$(MSBuildProjectDirectory)\$(EfcptTemplateDir)
- <_EfcptResolvedTemplateDir Condition="'$(_EfcptResolvedTemplateDir)' == ''">$(MSBuildThisFileDirectory)Defaults\Template
+ <_EfcptResolvedConfig>$(MSBuildProjectDirectory)\$(EfcptConfig)
+ <_EfcptResolvedConfig>$(MSBuildThisFileDirectory)Defaults\efcpt-config.json
+ <_EfcptResolvedRenaming>$(MSBuildProjectDirectory)\$(EfcptRenaming)
+ <_EfcptResolvedRenaming>$(MSBuildThisFileDirectory)Defaults\efcpt.renaming.json
+ <_EfcptResolvedTemplateDir>$(MSBuildProjectDirectory)\$(EfcptTemplateDir)
+ <_EfcptResolvedTemplateDir>$(MSBuildThisFileDirectory)Defaults\Template
<_EfcptIsUsingDefaultConfig>true
<_EfcptUseConnectionString>false
-
-
-
+
+
-
-
+
-
- <_EfcptDacpacPath Condition="$([System.IO.Path]::IsPathRooted('$(EfcptDacpac)'))">$(EfcptDacpac)
- <_EfcptDacpacPath Condition="!$([System.IO.Path]::IsPathRooted('$(EfcptDacpac)'))">$([System.IO.Path]::GetFullPath($([System.IO.Path]::Combine('$(MSBuildProjectDirectory)', '$(EfcptDacpac)'))))
+ <_EfcptDacpacPath>$(EfcptDacpac)
+ <_EfcptDacpacPath>$([System.IO.Path]::GetFullPath($([System.IO.Path]::Combine('$(MSBuildProjectDirectory)', '$(EfcptDacpac)'))))
<_EfcptUseDirectDacpac>true
-
+
-
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
- $(_EfcptResolvedDbContextName)
+ $(_EfcptResolvedDbContextName)
-
-
-
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
+
+