SchemaComparison reports comment differences that PublishChangesToProject silently ignores — header comments above CREATE never sync to project files
- Dominant language
- C#
- Stars
- 460
- Forks
- 29
- Avg merge
- 4d 9h
- Merged PRs (30d)
- 7
Description
- DacFx 162.3.566
- .NET 8, Windows 11
- Environment (local platform and source/target platforms):
`SchemaComparison.Compare()` detects differences that exist only in comments (including the conventional header comment block above `CREATE PROCEDURE`), but `SchemaComparisonResult.PublishChangesToProject()` generates an empty update plan for them and still reports `Success = true` with zero changed files. Additionally, even when a module has a *real* body change, the file update rewrites only the statement body — the header comment above `CREATE` in the project file is never updated from the source.
The two layers disagree about what an object is: the comparison layer diffs the full source text (header included), while the update planner works on the semantic model where the header lives only in the `SysCommentsObjectAnnotation` (`HeaderContents`, `CreateOffset`) and is not actionable. The result is differences that are shown to the user but can never be applied.
dacpac→database carries headers along with real changes, while database→project never does.
**Steps to Reproduce:**
```powershell
# point $dac at the DacFx payload (sqlpackage dotnet tool shown; NuGet lib/ works too)
$dac = "$env:USERPROFILE\.dotnet\tools\.store\microsoft.sqlpackage\162.3.566\microsoft.sqlpackage\162.3.566\tools\net8.0\any"
Add-Type -Path "$dac\runtimes\win\lib\net6.0\Microsoft.Data.SqlClient.dll"
Add-Type -Path "$dac\Microsoft.SqlServer.TransactSql.ScriptDom.dll"
Add-Type -Path "$dac\Microsoft.SqlServer.Dac.dll"
Add-Type -Path "$dac\Microsoft.SqlServer.Dac.Extensions.dll"
$work = Join-Path $env:TEMP 'dacfx-comment-repro'
Remove-Item $work -Recurse -Force -ErrorAction SilentlyContinue
New-Item -ItemType Directory "$work\proj\dbo\StoredProcedures" -Force | Out-Null
function Build-Dacpac([string]$path, [string]$sql) {
$model = [Microsoft.SqlServer.Dac.Model.TSqlModel]::new(
[Microsoft.SqlServer.Dac.Model.SqlServerVersion]::Sql150,
[Microsoft.SqlServer.Dac.Model.TSqlModelOptions]::new())
$model.AddObjects($sql)
$meta = [Microsoft.SqlServer.Dac.PackageMetadata]::new()
$meta.Name = 'Repro'; $meta.Version = '1.0.0.0'
[Microsoft.SqlServer.Dac.DacPackageExtensions]::BuildPackage($path, $model, $meta,
[Microsoft.SqlServer.Dac.PackageOptions]::new())
$model.Dispose()
}
# target project file: header ONE; source: header TWO — the ONLY difference is the header comment
$fileV = "-- header ONE`r`nCREATE PROCEDURE [dbo].[T]`r`nAS`r`nBEGIN`r`n SELECT 1 AS V`r`nEND"
$dbV = "-- header TWO`r`nCREATE PROCEDURE [dbo].[T]`r`nAS`r`nBEGIN`r`n SELECT 1 AS V`r`nEND"
Build-Dacpac "$work\source.dacpac" $dbV
[System.IO.File]::WriteAllText("$work\proj\dbo\StoredProcedures\T.sql", $fileV)
[System.IO.File]::WriteAllText("$work\proj\P.sqlproj",
'PMicrosoft.Data.Tools.Schema.Sql.Sql150DatabaseSchemaProvider')
$cmp = [Microsoft.SqlServer.Dac.Compare.SchemaComparison]::new(
[Microsoft.SqlServer.Dac.Compare.SchemaCompareDacpacEndpoint]::new("$work\source.dacpac"),
[Microsoft.SqlServer.Dac.Compare.SchemaCompareProjectEndpoint]::new(
"$work\proj\P.sqlproj", [string[]]@("$work\proj\dbo\StoredProcedures\T.sql"),
'Microsoft.Data.Tools.Schema.Sql.Sql150DatabaseSchemaProvider',
[Microsoft.SqlServer.Dac.DacExtractTarget]::SchemaObjectType))
$res = $cmp.Compare()
"differences listed : $($res.Differences.Count)"
$before = Get-Content "$work\proj\dbo\StoredProcedures\T.sql" -Raw
$pub = $res.PublishChangesToProject("$work\proj", [Microsoft.SqlServer.Dac.DacExtractTarget]::SchemaObjectType)
$after = Get-Content "$work\proj\dbo\StoredProcedures\T.sql" -Raw
"publish Success : $($pub.Success)"
"changed/added/deleted : $($pub.ChangedFiles.Count)/$($pub.AddedFiles.Count)/$($pub.DeletedFiles.Count)"
"file modified on disk : $($before -cne $after)"
```
**Expected behavior**
`PublishChangesToProject` updates comment-only differences it reported
**Impact**
Teams using the common SSMS template header (`-- Author / Create date / Description` above `CREATE`) get permanent phantom diffs in schema compare that no amount of clicking Apply resolves.
Contributor guide
Research direction
Start with SchemaComparison.Compare() and SchemaComparisonResult.PublishChangesToProject(), then trace how SysCommentsObjectAnnotation exposes HeaderContents and CreateOffset. Run the PowerShell reproduction against the stated DacFx version and inspect the generated project file. Done means comment-only differences produce an update and header comments are preserved when real module changes are published.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp, sql
- Domain
- databases, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100