Skip to content

Schema Compare: Fabric Warehouse platform detection + constraint script preservation - #2722

Closed
roramsay wants to merge 10 commits into
microsoft:mainfrom
roramsay:roramsay/schema-compare-fabric-platform
Closed

Schema Compare: Fabric Warehouse platform detection + constraint script preservation#2722
roramsay wants to merge 10 commits into
microsoft:mainfrom
roramsay:roramsay/schema-compare-fabric-platform

Conversation

@roramsay

Copy link
Copy Markdown

Three commits on this branch ship the sqltoolsservice changes for Schema Compare
on Microsoft Fabric Warehouse (Feature 1847587):

  1. 30d90abe — surface SourcePlatform / TargetPlatform on the result contract.
  2. 23a8ef56 — read platform from the comparison''s DSP via cached reflection
    (TSqlModel.Version returns Sql150 for SqlDwUnified due to an internal
    DacFx mapping bug — see InternalModelUtils.CalculateVersionsForPlatform).
  3. aa9a0761 — keep Fabric Warehouse constraint scripts under table diffs
    (SqlDwUnified-scoped carve-out in CreateDiffEntry''s starts-with-alter
    filter; behaviour unchanged for every other platform).

Companion PRs:

  • DacFx PR 2143938 (in flight) — cascade exclusion to hierarchical-child
    constraints under SqlDwUnified.
  • vscode-mssql PR (to be filed alongside this one) — platform badges +
    affected-constraints banner.

Spec: https://dev.azure.com/powerbi/Trident/_git/specs-dw/pullrequest/989687

Verified end-to-end against a live Fabric Warehouse + a Fabric .sqlproj:

  • Platform pill shows SqlDwUnified on both endpoints.
  • "Constraints added: Primary Key" banner appears above the diff editor
    for an Add table with a PK constraint.
  • The Monaco diff editor''s right pane shows CREATE TABLE followed by
    the standalone ALTER TABLE ... ADD CONSTRAINT [PK_...] PRIMARY KEY NONCLUSTERED ([col]) NOT ENFORCED; statement.
  • The generated deployment script includes that ALTER statement.

Test gap: a new unit test for CreateDiffEntry_PreservesConstraintAlterScriptUnderSqlDwUnified
is in the spec''s test design but not added in this PR — the SchemaCompare
unit-test project (Microsoft.SqlTools.ServiceLayer.UnitTests) currently
fails to compile against the DacFx 170.5 overlay (TSqlModelBuilder removed in
IntelliSense/SqlProjectIntelliSenseTests.cs). The test will be added once
the DacFx package version is officially bumped (gated on PR 2143938).

roramsay and others added 3 commits June 10, 2026 15:50
For Feature 1847587 (Schema Compare for Fabric Warehouse). The vscode-mssql
client needs to know which DacFx platform a comparison ran under so it can
display the dialect badge in the diff view header (e.g. `SqlDwUnified` for
Fabric Warehouse vs. `Sql160` for Azure SQL Database). Today the result has
no way to convey this without the client re-walking the DacFx model.

Adds `SourcePlatform` and `TargetPlatform` (nullable `string`) to both
`SchemaCompareResult` types (`Microsoft.SqlTools.SqlCore` for SSMS
direct-call consumers; `Microsoft.SqlTools.ServiceLayer` for the JSON-RPC
`schemaCompare/compare` response). Populated from
`ComparisonResult.SourceModel.Version.ToString()` and the target equivalent
after the comparison runs -- pass-through reads, no new I/O. Null-safe when
the comparison didn't produce a model.

Wired through `SchemaCompareOperation`:
- New `SourcePlatform` / `TargetPlatform` properties on the operation
  set by `Execute()` from the DacFx `ComparisonResult` models.
- `SchemaCompareService` reads these into the JSON-RPC
  `SchemaCompareResult` it returns to clients.

Tests: two new unit tests in `SchemaCompareTests.cs` covering the contract
shape (both `SchemaCompareResult` and the operation expose the properties,
default to `null`, and accept writes). End-to-end behaviour against live
comparisons is covered by integration tests for Feature 1847587.

No DacFx API change. No version bump required for this commit.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The public TSqlModel.Version surface maps SqlPlatforms.SqlDwUnified to
SqlServerVersion.Sql150 inside DacFx (InternalModelUtils.CalculateVersionsForPlatform),
so reading .Version.ToString() always returned 'Sql150' for Fabric Warehouse
models and mislabelled the platform pill in Schema Compare.

Read the comparison's normalized DSP from
SchemaComparisonResult.DataModel.DatabaseSchemaProvider.Platform via reflection.
DatabaseSchemaProvider is internal-abstract in DacFx but its .Platform property
returns the public SqlPlatforms enum, whose values map directly to the DSP-name
strings clients expect ('Sql160', 'SqlAzure', 'SqlDwUnified', etc.). Lookups
are cached statically; any reflection failure is logged and falls back to a
null platform string (the pill silently hides).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…diffs

CreateDiffEntry stripped any child script that started with `alter` to avoid
duplicating constraint DDL that the parent's CREATE TABLE already inlined for
legacy SQL Server. SqlDwUnified (Fabric Warehouse) never inlines PK/FK/UNIQUE/
CHECK/DEFAULT constraints into CREATE TABLE; they are always emitted as
standalone `ALTER TABLE ... ADD CONSTRAINT ...` statements. The filter
therefore discarded the only script that defined the constraint, so the diff
editor showed CREATE TABLE without the PK and the generated script was missing
the PK definition entirely.

Detect constraint children (PK/FK/UNIQUE/CHECK/DEFAULT) under a SqlDwUnified
comparison and preserve their scripts in that case. Behavior is unchanged for
all other platforms.

Move the cached reflection-based platform detector from SchemaCompareOperation
into SchemaCompareUtils so CreateDiffEntry can use it; add a
ConditionalWeakTable cache keyed by SchemaComparisonResult so the recursive
walk pays the reflection cost once per comparison, not once per diff entry.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@roramsay

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree company="Microsoft"

…e 1847587)

Implements the test design from the Schema Compare for Fabric Warehouse spec (Feature 1847587).

Unit tests (SchemaCompareTests.cs):

Extracts SchemaCompareUtils.ShouldPreserveAlterScriptForConstraint(typeName, platform) as a pure helper so the SqlDwUnified strip-on-alter carve-out is testable without manufacturing a sealed DacFx SchemaComparisonResult graph. Existing IsConstraintChildOnSqlDwUnified is now a thin wrapper. Adds 18 TestCase rows covering every constraint suffix under SqlDwUnified, non-constraint types under SqlDwUnified, every non-Fabric platform string a comparison can emit (Sql160/Sql150/SqlAzure/SqlAzureV12/SqlDw), null/empty type and platform inputs, substring-vs-suffix guard, and GetComparisonPlatform null-result short-circuit.

Integration tests (SchemaCompareFabricTests.cs):

Full 4-endpoint-pair x 7-scenario matrix (28 cells) via [TestCaseSource]. Scenarios: AllSupportedTypes, CompatibleAlterColumn, IncompatibleAlterColumn, PrimaryKey, Unique, ForeignKey, SelectionScope. Endpoint pairs: DacpacToDacpac, DacpacToProject, ProjectToDacpac, ProjectToProject. Fabric dacpacs are built offline at fixture setup via new TSqlModel(SqlServerVersion.SqlDwUnified, ...) + DacPackageExtensions.BuildPackage so the suite requires no live Fabric Warehouse.

Per-cell assertions (per spec lines 309-316): comparison validity + IsEqual=false + Differences.Any(); SourcePlatform == TargetPlatform == SqlDwUnified; constraints folded under parent SqlTable diff (not surfaced as top-level entries); constraint child carries ADD CONSTRAINT NONCLUSTERED NOT ENFORCED script; selection-scope IncludeOnly(OrdersScope) yields a Generate Script output that references zero unrelated tables or constraints (locks in the Prototype 3 empirical regression that motivated DacFx PR 2143938); project-target round-trip converges to IsEqual after publish.

Live Fabric publish (per-cell assertion 7) is intentionally manual-only per the spec; it is exercised by the WSR matrix, not automated here.

Fixtures (test/.../SchemaCompare/Fabric/*.sql): 14 minimal T-SQL scripts confined to the Fabric-supported data type list, with all constraints scripted as NONCLUSTERED NOT ENFORCED. Plus emptyFabricTemplate.sqlproj with DSP=SqlDwUnifiedDatabaseSchemaProvider for the Project endpoint cases.

Requires DacFx >= 170.5.20 (the published build that ships PR 2143938's cascade fix). The sts-version-bump that flips Packages.props onto that DacFx is a separate change and is not included here.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@roramsay

Copy link
Copy Markdown
Author

Added the test scenarios from the spec (Feature 1847587 §Test design) in commit 40f96df:

Unit tests (test/Microsoft.SqlTools.ServiceLayer.UnitTests/SchemaCompare/SchemaCompareTests.cs)
Extracted SchemaCompareUtils.ShouldPreserveAlterScriptForConstraint(typeName, platform) as a pure helper so the SqlDwUnified strip-on-alter carve-out is testable without manufacturing a sealed DacFx SchemaComparisonResult graph. Added 18 TestCase rows covering every constraint suffix under SqlDwUnified, non-constraint types under SqlDwUnified, every non-Fabric platform string a comparison can emit (Sql160 / Sql150 / SqlAzure / SqlAzureV12 / SqlDw), null/empty inputs, substring-vs-suffix guard, and GetComparisonPlatform null-result short-circuit. 26/26 SchemaCompare unit tests pass locally.

Integration tests (test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SchemaCompare/SchemaCompareFabricTests.cs)
Full 4 endpoint pair × 7 scenario matrix (28 cells) via [TestCaseSource]. Scenarios: AllSupportedTypes, CompatibleAlterColumn, IncompatibleAlterColumn, PrimaryKey, Unique, ForeignKey, SelectionScope. Endpoint pairs: DacpacToDacpac, DacpacToProject, ProjectToDacpac, ProjectToProject.

Fabric dacpacs are built offline at fixture setup via new TSqlModel(SqlServerVersion.SqlDwUnified, …) + DacPackageExtensions.BuildPackage so the suite requires no live Fabric Warehouse. Fixtures (14 minimal Fabric-T-SQL .sql files plus emptyFabricTemplate.sqlproj with <DSP>SqlDwUnifiedDatabaseSchemaProvider</DSP>) live alongside the test.

Per-cell assertions implemented per spec lines 309-316:

  1. IsValid / IsEqual=false / Differences.Any()
  2. SourcePlatform == TargetPlatform == "SqlDwUnified"
  3. Constraints folded under parent SqlTable diff (zero top-level constraint diffs)
  4. Constraint child carries ADD CONSTRAINT … NONCLUSTERED … NOT ENFORCED script preserved by the SqlDwUnified carve-out in CreateDiffEntry
  5. Selection-scope: IncludeOnly(OrdersScope) ⇒ generated script references zero unrelated tables and zero unrelated constraint names (locks in the Prototype 3 empirical regression — the 19 leaked PK statements — that motivated DacFx PR 2143938)
  6. Project-target round-trip: re-compare after publish converges to IsEqual=true
  7. Live Fabric publish (manual/WSR only, intentionally not automated per spec)

Local run: 28/28 Fabric integration tests pass (~17 s) against a locally-built DacFx 170.5.20-local that includes PR 2143938's cascade fix.

⚠️ CI dependency

These tests require the DacFx NuGet that ships PR 2143938 (cascade exclusion to hierarchical-child constraints). On this branch Packages.props still references 170.4.80-preview — that bump is intentionally not part of this commit because it is the same change tracked as the sts-version-bump follow-up. The tests will turn green in CI as soon as DacFx PR 2143938 publishes and we bump the version pin.

Linked vscode-mssql PR with the webview-side tests: microsoft/vscode-mssql#22340.

Public DacFx 170.5.38-preview ships the constraint cascade-exclusion fix (DacFx PR 2143938) that the SqlDwUnified Schema Compare integration tests depend on. Replaces the temporary 170.4.80-preview pin. Local run: 26/26 SchemaCompare unit tests + 28/28 Fabric integration tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@roramsay

roramsay commented Jul 1, 2026

Copy link
Copy Markdown
Author

Bumped Microsoft.SqlServer.DacFx to 170.5.38-preview (commit 5354cee) — this public preview ships DacFx PR 2143938 (cascade exclusion for hierarchical-child constraints) that the SqlDwUnified Schema Compare tests depend on. Replaces the placeholder 170.4.80-preview pin.

Local verification against 170.5.38-preview:

  • Restore + build: clean (Schema Compare projects; unrelated IDE0241 analyzer noise in TestDriver.Tests / PerfTests / Migration.IntegrationTests is pre-existing and untouched by this change)
  • SchemaCompareTests unit tests: 26/26 pass (~2.7 s)
  • SchemaCompareFabricTests integration tests: 28/28 pass (~17 s) — full 4-endpoint × 7-scenario matrix green with no [Ignore] markers.

CI dependency called out in the previous review comment is resolved.

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown

As part of updating the dependencies in Packages.props we require that any PRs opened also verify that
they've done the following checks.

Please respond to this comment verifying that you've done the appropriate validation (or explain why it's not necessary) before merging in the PR

  • Built and tested the change locally to validate that the update doesn't cause any regressions and fixes the issues intended
  • Tested changes on all major platforms
    • Windows
    • Linux
    • Mac
  • Check the source repo for any open issues with the release being updated to (if available)

@roramsay

roramsay commented Jul 1, 2026

Copy link
Copy Markdown
Author

Responding to the Packages.props update checklist:

  • Built and tested the change locally to validate that the update doesn't cause any regressions and fixes the issues intended

    • Restore + build of Schema Compare projects on 170.5.38-preview: clean. (Three pre-existing IDE0241 errors in TestDriver.Tests / PerfTests / Migration.IntegrationTests are unrelated — they reproduce on the branch head before the bump and are analyzer noise from SDK 10.0.301, not caused by DacFx.)
    • Broader Schema Compare unit suite (SchemaCompare + Dacpac + SqlProject): 32/32 pass (~1s).
    • SchemaCompareTests unit tests: 26/26 pass (~2.7s).
    • SchemaCompareFabricTests integration tests: 28/28 pass (~17s) — full 4-endpoint × 7-scenario matrix. This is the intended fix: prior to 170.5.38-preview these tests required the placeholder 170.5.20-local package (containing DacFx PR 2143938's cascade exclusion). The public preview now ships that fix, so the temporary pin can be removed.
  • Tested changes on all major platforms

    • Windows — verified locally (Windows 11, .NET SDK 10.0.301, all tests above).
    • Linux — not run locally; will be exercised by CI. Risk assessment: the change is a pure NuGet version bump in Packages.props; DacFx 170.5.38-preview is a managed .NET package that already targets net8.0 cross-platform (STS already runs on Linux against DacFx on main). Both the runtime consumer (SchemaCompareUtils.ShouldPreserveAlterScriptForConstraint — pure string comparison) and the test fixtures (in-memory TSqlModel + DacPackageExtensions.BuildPackage, no shelling out to platform tools) are OS-agnostic.
    • Mac — same posture as Linux; will be exercised by CI. No platform-specific code paths introduced.
  • Check the source repo for any open issues with the release being updated to

@roramsay

roramsay commented Jul 1, 2026

Copy link
Copy Markdown
Author

Cross-referenced the DacFx 170.5.38-preview release notes against this PR:

Directly validates this bump — the intended fix is called out verbatim:

Fixes Schema Compare against a Microsoft Fabric Warehouse leaking primary key and other constraints of excluded tables into the generated deployment script

That is DacFx PR 2143938 (the cascade-exclusion fix). Our FabricCompare_SelectionScope_* integration tests (4 endpoint-pair cells) lock this in by asserting zero unrelated PK / constraint statements in the generated script under IncludeOnly(OrdersScope) — the Prototype 3 regression that motivated the fix. All 4 cells pass on 170.5.38-preview.

Also relevant, no code change needed:

  • Fixes Extract to a SQL project emitting per-batch SET ANSI_NULLS / SET QUOTED_IDENTIFIER options into the generated .sqlproj, which broke deployment of objects that require those options on Microsoft Fabric — intersects the Project-target half of our matrix (*_DacpacToProject, *_ProjectToDacpac, *_ProjectToProject = 21 of 28 cells). All 21 pass, and the round-trip assertion (IsEqual=true after publish) confirms Project→Dacpac re-comparison converges as expected.

Not applicable to this PR (informational):

  • Adds SkipExistingModelValidation on TSqlObjectOptions — SQL projects IntelliSense; unused by Schema Compare.
  • Fixes DoNotDropExtendedProperties=True conflict (Package SMO and T-SQL LangService EULAs in sqltoolsservice archive. #139) — extended properties; not exercised by Fabric SC fixtures.
  • Fixes SQL Server 2027 SqlExternalLanguage reverse-engineering — SQL Server 2027 target platform; orthogonal.
  • Updates Microsoft.SqlServer.TransactSql.ScriptDom to 180.37.3 — transitive; no STS callsite change needed and full 32-test broader Schema Compare unit suite is green.

Net: the release notes strengthen the case for this bump (they're the public confirmation of the fix our tests were waiting on) and none of the other changes require action in this PR.

@roramsay
roramsay marked this pull request as ready for review July 1, 2026 17:51
Copilot AI review requested due to automatic review settings July 1, 2026 17:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Fabric Warehouse (SqlDwUnified) awareness to Schema Compare results and preserves Fabric-specific constraint ALTER scripts so diffs and generated deployment scripts don’t drop constraint definitions.

Changes:

  • Expose SourcePlatform / TargetPlatform on Schema Compare operation + result contracts, populated via reflected DSP platform detection.
  • Preserve child ALTER TABLE ... ADD CONSTRAINT scripts for SqlDwUnified constraint diffs (PK/FK/UQ/CHECK/DEFAULT) instead of stripping “alter”-prefixed scripts.
  • Add an offline Fabric ↔ Fabric integration test matrix (dacpac/project combinations) plus Fabric SQL fixtures and an SDK-style Fabric .sqlproj template; bump DacFx package version.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
test/Microsoft.SqlTools.ServiceLayer.UnitTests/SchemaCompare/SchemaCompareTests.cs Adds unit coverage for platform properties and SqlDwUnified constraint-script preservation helper.
test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SchemaCompare/SqlProjects/emptyFabricTemplate.sqlproj Adds a Fabric-targeted SQL project template (SqlDwUnified DSP) for integration testing.
test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SchemaCompare/SchemaCompareFabricTests.cs Adds Fabric integration matrix tests validating platform detection, constraint folding, script preservation, selection-scope behavior, and project round-trip.
test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SchemaCompare/Fabric/FabricWidenColumn_Target.sql Adds Fabric fixture for widening-column target schema.
test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SchemaCompare/Fabric/FabricWidenColumn_Source.sql Adds Fabric fixture for widening-column source schema.
test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SchemaCompare/Fabric/FabricUnique_Target.sql Adds Fabric fixture for UNIQUE scenario target schema.
test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SchemaCompare/Fabric/FabricUnique_Source.sql Adds Fabric fixture for UNIQUE scenario source schema.
test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SchemaCompare/Fabric/FabricSelectionScope_Target.sql Adds Fabric fixture for selection-scope target schema.
test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SchemaCompare/Fabric/FabricSelectionScope_Source.sql Adds Fabric fixture for selection-scope source schema.
test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SchemaCompare/Fabric/FabricPrimaryKey_Target.sql Adds Fabric fixture for PK scenario target schema.
test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SchemaCompare/Fabric/FabricPrimaryKey_Source.sql Adds Fabric fixture for PK scenario source schema.
test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SchemaCompare/Fabric/FabricNarrowColumn_Target.sql Adds Fabric fixture for narrowing-column target schema.
test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SchemaCompare/Fabric/FabricNarrowColumn_Source.sql Adds Fabric fixture for narrowing-column source schema.
test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SchemaCompare/Fabric/FabricForeignKey_Target.sql Adds Fabric fixture for FK scenario target schema.
test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SchemaCompare/Fabric/FabricForeignKey_Source.sql Adds Fabric fixture for FK scenario source schema.
test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SchemaCompare/Fabric/FabricAllTypes_Target.sql Adds Fabric fixture for supported-types target schema.
test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SchemaCompare/Fabric/FabricAllTypes_Source.sql Adds Fabric fixture for supported-types source schema.
src/Microsoft.SqlTools.SqlCore/SchemaCompare/SchemaCompareUtils.cs Adds SqlDwUnified constraint ALTER preservation logic and reflected/cached platform detection.
src/Microsoft.SqlTools.SqlCore/SchemaCompare/SchemaCompareOperation.cs Hoists detected platform onto operation for propagation to result contract.
src/Microsoft.SqlTools.SqlCore/SchemaCompare/Contracts/SchemaCompareResults.cs Adds platform fields to SqlCore result contract.
src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareService.cs Wires operation platform fields into the ServiceLayer response payload.
src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/Contracts/SchemaCompareRequest.cs Adds platform fields to ServiceLayer JSON-RPC response contract.
Packages.props Bumps Microsoft.SqlServer.DacFx to 170.5.38-preview.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Microsoft.SqlTools.SqlCore/SchemaCompare/SchemaCompareUtils.cs
Comment thread Packages.props
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 1, 2026 19:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 7 comments.

Comment thread src/Microsoft.SqlTools.SqlCore/SchemaCompare/SchemaCompareUtils.cs Outdated
- SchemaCompareResults / SchemaCompareRequest: XML docs now correctly identify SourcePlatform / TargetPlatform as short names of DacFx SqlPlatforms values sourced from DatabaseSchemaProvider.Platform (not SqlServerVersion / TSqlModel.Version, which reports Sql150 for Fabric Warehouse).

- SchemaCompareTests: updated rationale comment to match the reflection-based GetComparisonPlatform implementation used by this PR.

- SchemaCompareFabricTests: simplified redundant IndexOf + CountOccurrences assertion for excluded-table check to a single IndexOf, and removed the now-unused CountOccurrences helper.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@roramsay

roramsay commented Jul 1, 2026

Copy link
Copy Markdown
Author

Reviewed the six PR-review comments from @copilot-pull-request-reviewer and addressed the five with actionable, valid suggestions in commit c2f73df. The DacFx-bump comment (#6) is dismissed as its premise is empirically false — see rationale below.

Addressed (commit c2f73df):

  1. SchemaCompareUtils.cs:275 — ConditionalWeakTable race. Already resolved by autofix commit b5ef119 (GetValue(result, factory) atomic API). No further change needed.

  2. SchemaCompareResults.cs:42 — XML docs referenced SqlServerVersion. Updated to identify the values as short names of DacFx SqlPlatforms sourced from DatabaseSchemaProvider.Platform via SchemaCompareUtils.GetComparisonPlatform, and called out explicitly that TSqlModel.Version reports Sql150 for Fabric Warehouse (which is why we can't use it).

  3. SchemaCompareRequest.cs:64 — same doc mismatch on the ServiceLayer contract. Same fix applied.

  4. SchemaCompareTests.cs:143 — outdated rationale comment. Rewrote to describe the actual reflection-based GetComparisonPlatform implementation and to explain why TSqlModel.Version isn't the source of truth here.

  5. SchemaCompareFabricTests.cs:355 — redundant IndexOf >= 0 && CountOccurrences > 0. Simplified to a single IndexOf check; removed the now-unused CountOccurrences helper.

Dismissed:

  1. Packages.props:25 — DacFx bump claimed to break TSqlModelBuilder.LoadModel callsites. The premise is empirically false — no such removal or relocation exists in 170.5.38-preview:
    • Full ServiceLayer + UnitTests + IntegrationTests build against 170.5.38-preview is clean (0 warnings, 0 errors on the Schema Compare-touching projects).
    • The 9 TSqlModelBuilder.LoadModel(...) callsites in SqlProjectsService.cs and the IntelliSense unit tests all compile without deprecation or missing-type diagnostics.
    • The 170.5.38-preview release notes list no TSqlModelBuilder change; the PR description does not mention such a removal either.

Post-fix verification against 170.5.38-preview:

  • Schema Compare unit tests: 26/26 pass (~0.06 s)
  • Fabric integration tests: 28/28 pass (~14 s)

- SchemaCompareUtils.cs: Logger.Warning now logs the full exception (type + message + stack) via ex.ToString(), not just ex.Message. Matches the Logger.Error(Exception) pattern already used elsewhere in Logger.cs.

- SchemaCompareTests.cs: SchemaCompareOperationExposesSourceAndTargetPlatformProperties comment corrected to describe the actual population path (SchemaCompareUtils.GetComparisonPlatform via reflection), not the pre-PR TSqlModel.Version pass-through.

- SchemaCompareFabricTests.cs: removed three unused SqlPrimaryKeyConstraintType / SqlForeignKeyConstraintType / SqlUniqueConstraintType constants (dead code — assertions use ConstraintTypeSuffixes).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 1, 2026 19:24
@roramsay

roramsay commented Jul 1, 2026

Copy link
Copy Markdown
Author

Second-pass review fixes shipped in commit a13fa63 and all applicable threads resolved:

New fixes in a13fa63:

  • SchemaCompareUtils.cs:320Logger.Warning now logs the full exception (ex.ToString() → type + message + stack) instead of just ex.Message, matching the Logger.Error(Exception) pattern already used in Logger.cs.
  • SchemaCompareTests.cs:170 (SchemaCompareOperationExposesSourceAndTargetPlatformProperties) — rewrote the rationale comment to describe the actual population path (SchemaCompareUtils.GetComparisonPlatform via reflection) and call out why TSqlModel.Version isn't used.
  • SchemaCompareFabricTests.cs:50-55 — removed three unused constraint-type constants (SqlPrimaryKeyConstraintType / SqlForeignKeyConstraintType / SqlUniqueConstraintType); assertions rely on ConstraintTypeSuffixes instead.

Thread status:

  • 12 of 13 review threads resolved.
  • 1 thread intentionally left open: Packages.props:25 — DacFx bump. Its premise (170.5.38-preview removes/relocates TSqlModelBuilder.LoadModel) is empirically false — build + tests pass on the bumped version — but I'm leaving that thread for a human maintainer to close so the dismissal is on record.

Post-fix verification (170.5.38-preview):

  • Schema Compare unit tests: 26/26 pass (~0.05s)
  • Fabric integration tests: 28/28 pass (~15s)
  • Build: 0 warnings, 0 errors on all touched projects.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 3 comments.

Comment thread src/Microsoft.SqlTools.SqlCore/SchemaCompare/SchemaCompareUtils.cs Outdated
Comment thread src/Microsoft.SqlTools.SqlCore/SchemaCompare/SchemaCompareUtils.cs Outdated
Comment thread src/Microsoft.SqlTools.SqlCore/SchemaCompare/SchemaCompareUtils.cs Outdated
…mpat

Type.GetProperty(string) defaults to BindingFlags.Public|Instance only, so if DacFx ever flips DataModel from non-public to public, or flips DatabaseSchemaProvider/Platform from public to non-public, the reflection lookup silently fails and permanently disables platform detection via s_reflectionInitFailed.

All three GetProperty callsites (DataModel, DatabaseSchemaProvider, Platform) now use Public|NonPublic|Instance so the lookup tolerates accessibility changes across DacFx versions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@roramsay

roramsay commented Jul 1, 2026

Copy link
Copy Markdown
Author

Addressed all three reflection binding-flag comments in commit 339d8d6:

All three Type.GetProperty(string) callsites in SchemaCompareUtils.cs (DataModel at line 348, DatabaseSchemaProvider at line 293, Platform at line 306) now pass BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance so the lookup tolerates future DacFx accessibility changes without silently disabling platform detection (which would otherwise be permanent thanks to the s_reflectionInitFailed short-circuit).

Verification (170.5.38-preview):

  • Schema Compare unit tests: 26/26 pass (~0.06s)
  • Fabric integration tests: 28/28 pass (~14s)

Threads resolved.

Copilot AI review requested due to automatic review settings July 7, 2026 22:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 22 out of 22 changed files in this pull request and generated 4 comments.

Comment on lines 88 to 92
// Child scripts that do not use alter need to be added if they are being changed, ex: "EXECUTE sp_addextendedproperty...".
// Don't add scripts that start with alter because those are handled by a top level element's create
if (!sourceScript.ToLowerInvariant().StartsWith("alter"))
if (keepAlterScript || !sourceScript.ToLowerInvariant().StartsWith("alter"))
{
diffEntry.SourceScript = FormatScript(sourceScript);
Comment on lines +292 to +305
PropertyInfo dspProp = s_dspProp ?? dataModel.GetType().GetProperty(
"DatabaseSchemaProvider",
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if (dspProp == null)
{
return null;
}
s_dspProp = dspProp;

object dsp = dspProp.GetValue(dataModel);
if (dsp == null)
{
return null;
}
Comment on lines +307 to +317
PropertyInfo platformProp = s_platformProp ?? dsp.GetType().GetProperty(
"Platform",
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if (platformProp == null)
{
return null;
}
s_platformProp = platformProp;

object platformValue = platformProp.GetValue(dsp);
return platformValue?.ToString();
Comment on lines +45 to +46
/// Null if the
/// platform could not be detected (e.g. the comparison was never run).

@llali llali left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

both changes in this PR can be fixed in dacfx directly and that's what I recommend doing

// .Platform is a public abstract SqlPlatforms property (a public enum), and
// the cascade fix in PR 2143938 confirms this value is reliably populated.
string comparisonPlatform = SchemaCompareUtils.GetComparisonPlatform(this.ComparisonResult);
this.SourcePlatform = comparisonPlatform;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

source and target are the same?

@roramsay

roramsay commented Jul 8, 2026

Copy link
Copy Markdown
Author

Closing this PR and moving the changes into DacFx

@roramsay roramsay closed this Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants