Skip to content

Commit 17b0d88

Browse files
authored
refactor: Refactor SQL project detection to prioritize SDK attribute over MSBuild properties (#58)
1 parent 5f18796 commit 17b0d88

3 files changed

Lines changed: 102 additions & 14 deletions

File tree

samples/database-first-sql-generation/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,10 @@ database-first-sql-generation/
8181

8282
### Automatic Detection
8383

84-
JD.Efcpt.Build uses MSBuild properties to detect SQL projects:
84+
JD.Efcpt.Build detects SQL projects by checking the project file's SDK attribute:
8585

86-
- **Microsoft.Build.Sql**: Checks for `$(DSP)` property
87-
- **MSBuild.Sdk.SqlProj**: Checks for `$(SqlServerVersion)` property
86+
- **SDK-based projects**: Checks if the `Sdk` attribute contains `Microsoft.Build.Sql` or `MSBuild.Sdk.SqlProj`
87+
- **Legacy SSDT projects**: Falls back to checking MSBuild properties (`$(DSP)` or `$(SqlServerVersion)`)
8888

8989
When detected, it runs SQL generation instead of EF Core generation.
9090

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
using Microsoft.Build.Framework;
2+
using Microsoft.Build.Utilities;
3+
4+
namespace JD.Efcpt.Build.Tasks;
5+
6+
/// <summary>
7+
/// MSBuild task that detects whether the current project is a SQL database project.
8+
/// Uses the SqlProjectDetector to check for SDK-based projects first, then falls back to property-based detection.
9+
/// </summary>
10+
// Note: Fully qualifying Task to avoid ambiguity with System.Threading.Tasks.Task
11+
public sealed class DetectSqlProject : Microsoft.Build.Utilities.Task
12+
{
13+
/// <summary>
14+
/// Gets or sets the full path to the project file.
15+
/// </summary>
16+
[Required]
17+
public string? ProjectPath { get; set; }
18+
19+
/// <summary>
20+
/// Gets or sets the SqlServerVersion property (for legacy SSDT detection).
21+
/// </summary>
22+
public string? SqlServerVersion { get; set; }
23+
24+
/// <summary>
25+
/// Gets or sets the DSP property (for legacy SSDT detection).
26+
/// </summary>
27+
public string? DSP { get; set; }
28+
29+
/// <summary>
30+
/// Gets a value indicating whether the project is a SQL project.
31+
/// </summary>
32+
[Output]
33+
public bool IsSqlProject { get; private set; }
34+
35+
/// <summary>
36+
/// Executes the task to detect if the project is a SQL database project.
37+
/// </summary>
38+
/// <returns>True if the task executes successfully; otherwise, false.</returns>
39+
public override bool Execute()
40+
{
41+
if (string.IsNullOrWhiteSpace(ProjectPath))
42+
{
43+
Log.LogError("ProjectPath is required.");
44+
return false;
45+
}
46+
47+
// First, check if project uses a modern SQL SDK via SDK attribute
48+
var usesModernSdk = SqlProjectDetector.IsSqlProjectReference(ProjectPath);
49+
50+
if (usesModernSdk)
51+
{
52+
IsSqlProject = true;
53+
Log.LogMessage(MessageImportance.Low,
54+
"Detected SQL project via SDK attribute: {0}", ProjectPath);
55+
return true;
56+
}
57+
58+
// Fall back to property-based detection for legacy SSDT projects
59+
var hasLegacyProperties = !string.IsNullOrEmpty(SqlServerVersion) || !string.IsNullOrEmpty(DSP);
60+
61+
if (hasLegacyProperties)
62+
{
63+
IsSqlProject = true;
64+
Log.LogMessage(MessageImportance.Low,
65+
"Detected SQL project via MSBuild properties (legacy SSDT): {0}", ProjectPath);
66+
return true;
67+
}
68+
69+
IsSqlProject = false;
70+
Log.LogMessage(MessageImportance.Low,
71+
"Not a SQL project: {0}", ProjectPath);
72+
return true;
73+
}
74+
}

src/JD.Efcpt.Build/buildTransitive/JD.Efcpt.Build.targets

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,31 @@
1010
<!-- Derive UseNullableReferenceTypes from project's Nullable setting for zero-config scenarios -->
1111
<EfcptConfigUseNullableReferenceTypes Condition="'$(EfcptConfigUseNullableReferenceTypes)'=='' and ('$(Nullable)'=='enable' or '$(Nullable)'=='Enable')">true</EfcptConfigUseNullableReferenceTypes>
1212
<EfcptConfigUseNullableReferenceTypes Condition="'$(EfcptConfigUseNullableReferenceTypes)'=='' and '$(Nullable)'!=''">false</EfcptConfigUseNullableReferenceTypes>
13+
</PropertyGroup>
1314

14-
<!--
15-
SQL Project Detection: Detect if this is a SQL database project (not an EF Core consumer project).
15+
<!--
16+
SQL Project Detection: Detect if this is a SQL database project (not an EF Core consumer project).
1617
17-
Detection logic:
18-
- Microsoft.Build.Sql SDK: Check for $(SqlServerVersion) or $(DSP) properties
19-
- MSBuild.Sdk.SqlProj: Check for $(SqlServerVersion)
18+
Detection logic (in priority order):
19+
1. Check if project file Sdk attribute references Microsoft.Build.Sql or MSBuild.Sdk.SqlProj
20+
2. Fall back to MSBuild properties ($(SqlServerVersion) or $(DSP)) for legacy SSDT projects
2021
21-
This must be in the targets file (not props) because SDK properties like SqlServerVersion
22-
are not available when props files are evaluated.
23-
-->
24-
<_EfcptIsSqlProject Condition="'$(_EfcptIsSqlProject)'=='' and ('$(SqlServerVersion)' != '' or '$(DSP)' != '')">true</_EfcptIsSqlProject>
25-
<_EfcptIsSqlProject Condition="'$(_EfcptIsSqlProject)'==''">false</_EfcptIsSqlProject>
26-
</PropertyGroup>
22+
This must be in the targets file (not props) because SDK properties like SqlServerVersion
23+
are not available when props files are evaluated.
24+
-->
25+
<Target Name="_EfcptDetectSqlProject" BeforeTargets="BeforeBuild;BeforeRebuild">
26+
<DetectSqlProject
27+
ProjectPath="$(MSBuildProjectFullPath)"
28+
SqlServerVersion="$(SqlServerVersion)"
29+
DSP="$(DSP)">
30+
<Output TaskParameter="IsSqlProject" PropertyName="_EfcptIsSqlProject" />
31+
</DetectSqlProject>
32+
33+
<!-- Defensive: ensure the property is always set, even if the task encounters an unexpected scenario -->
34+
<PropertyGroup>
35+
<_EfcptIsSqlProject Condition="'$(_EfcptIsSqlProject)'==''">false</_EfcptIsSqlProject>
36+
</PropertyGroup>
37+
</Target>
2738

2839
<!--
2940
Determine the correct task assembly path based on MSBuild runtime and version.
@@ -117,6 +128,9 @@
117128
<UsingTask TaskName="JD.Efcpt.Build.Tasks.AddSqlFileWarnings"
118129
AssemblyFile="$(_EfcptTaskAssembly)" />
119130

131+
<UsingTask TaskName="JD.Efcpt.Build.Tasks.DetectSqlProject"
132+
AssemblyFile="$(_EfcptTaskAssembly)" />
133+
120134
<!--
121135
SDK Version Check: Warns users when a newer SDK version is available.
122136
Opt-in via EfcptCheckForUpdates=true. Results are cached for 24 hours.

0 commit comments

Comments
 (0)