Pull a SQL Server database's schema into a SQL database project (.sqlproj). Modern Microsoft.Build.Sql SDK-style projects are the first-class target; legacy SSDT .sqlproj files are supported on a best-effort basis.
All schema-compare and project-publish operations go through the public DacFx APIs (SchemaCompareProjectEndpoint and SchemaComparisonResult.PublishChangesToProject), so the tool needs no Visual Studio, vswhere, MSBuild discovery, or hand-rolled folder-structure tables.
dotnet tool install --global SqlProjectSync.Toolsqlproj-sync sync <scmp-path> [--preview] [-v <verbosity>] [--folder-structure <layout>]Examples:
# Preview what would change
sqlproj-sync sync ./CompareToProject.scmp --preview
# Apply changes with debug logging
sqlproj-sync sync ./CompareToProject.scmp -v Debug
# Pick a different DacFx folder layout (default: SchemaObjectType)
sqlproj-sync sync ./CompareToProject.scmp --folder-structure SchemaOptions:
| Flag | Default | Meaning |
|---|---|---|
--preview |
off | Print the projected changes without writing to disk. |
-v, --verbosity |
Information |
One of Trace, Debug, Information, Warning, Error, Critical, None. |
--folder-structure |
SchemaObjectType |
DacFx DacExtractTarget — controls how files are laid out in the project. |
The .scmp file is the same shape as the one Azure Data Studio / SqlPackage produce; the tool resolves the target .sqlproj by walking up directories from the .scmp and matching ProjectBasedModelProvider.Name.
Exit codes: 0 success (or no differences), 1 schema sync failed, 2 comparison returned an invalid state.
using SqlProjectSync;
var comparison = SchemaSync.Compare("CompareToProject.scmp");
if (comparison.IsEqual)
{
Console.WriteLine("Already in sync.");
return;
}
var publish = SchemaSync.Apply(comparison);
foreach (var added in publish.AddedFiles) Console.WriteLine($"+ {added}");
foreach (var del in publish.DeletedFiles) Console.WriteLine($"- {del}");
foreach (var chg in publish.ChangedFiles) Console.WriteLine($"~ {chg}");Pass a SyncOptions record to override the target project path, the source connection string, the DSP, or the folder structure. Pass an ILogger to capture structured progress events.
Phases 0 – 6 are landed. See PLAN.md for what each phase covered and the per-phase follow-on items.
The legacy .sqlproj compat suite (in tests/SqlProjectSync.IntegrationTests/LegacyCompatTests.cs) runs as part of the default dotnet test. DacFx's PublishChangesToProject only writes/deletes the .sql files; the matching <Build Include="..."/> items in the legacy XML are patched afterwards by LegacyProjectPatcher using the preview Microsoft.SqlServer.DacFx.Projects package. The nightly legacy-compat.yml workflow still runs the suite with continue-on-error: true as a defensive net.
dotnet build -c Release SqlProjectSync.slnx
dotnet test -c Release tests/SqlProjectSync.Tests/SqlProjectSync.Tests.csproj
dotnet test -c Release tests/SqlProjectSync.IntegrationTests/SqlProjectSync.IntegrationTests.csproj -- --filter-not-trait Style=Legacy
dotnet pack -c Release src/SqlProjectSync/SqlProjectSync.csproj -o artifacts
dotnet pack -c Release src/SqlProjectSync.Tool/SqlProjectSync.Tool.csproj -o artifactsIntegration tests require Docker (a SQL Server 2022 container is spun up per test session via Testcontainers). Unit tests have no external dependencies.
MIT — see LICENSE.