Overview
NuGet.Services.DatabaseMigration is a small but critical shared library that provides the reusable scaffolding for running Entity Framework code-first migrations against NuGet’s family of SQL Server databases. It is not itself an executable — it defines the job base class, the context interfaces, and the migration execution/validation logic that every concrete migration runner inherits from.
The library ships as an internal NuGet package (versioned with GalleryPackageVersion) and is consumed by the DatabaseMigrationTools executable project, which wires up the actual EF DbMigrator instances for each database target.
This library targets net472 (full .NET Framework), aligning with the legacy EF6 /
System.Data.SqlClient stack used by NuGet Gallery’s existing SQL layer. It is intentionally not migrated to EF Core.Role in the NuGetGallery Ecosystem
Consumer: DatabaseMigrationTools
The sole consumer of this library. Provides concrete
*DbMigrationContext implementations and MigrationContextFactory, then calls JobRunner.RunOnce followed by a 30-second Thread.Sleep to flush Application Insights telemetry before process exit.Job Infrastructure: NuGet.Jobs.Common
JsonConfigurationJob handles JSON-based configuration loading, Autofac DI wiring, and structured logging. Job overrides Init, Run, ConfigureAutofacServices, and ConfigureJobServices.Key Files and Classes
| File | Class / Type | Purpose |
|---|---|---|
Job.cs | Job | Main job entry point. Reads the MigrationTargetDatabase argument, creates the context via the factory, validates migration history, logs the SQL script, and calls DbMigrator.Update(). |
IMigrationContext.cs | IMigrationContext | Contract for a migration context: exposes SqlConnection, SqlConnectionAccessToken, and a Func<DbMigrator> factory delegate. Extends IDisposable. |
IMigrationContextFactory.cs | IMigrationContextFactory | Single-method factory: CreateMigrationContextAsync(string targetDb, IServiceProvider). Enables DI-friendly context creation without coupling the job to concrete EF types. |
BaseDbMigrationContext.cs | BaseDbMigrationContext | Concrete base that holds SqlConnection, SqlConnectionAccessToken, and GetDbMigrator. Includes SetSqlConnectionAccessToken() to re-apply the Microsoft Entra ID token if the connection was closed and re-opened. |
MigrationTargetDatabaseArgumentNames.cs | MigrationTargetDatabaseArgumentNames | Static string constants for the four valid MigrationTargetDatabase argument values: GalleryDatabase, SupportRequestDatabase, ValidationDatabase, CatalogValidationDatabase. |
Dependencies
NuGet Package References
| Package | Purpose |
|---|---|
EntityFramework | EF6 DbMigrator, MigratorScriptingDecorator, and migration infrastructure |
System.Data.SqlClient | SqlConnection for direct SQL Server connectivity |
Internal Project References
| Project | Purpose |
|---|---|
NuGet.Jobs.Common | Provides JsonConfigurationJob, JobConfigurationManager, and JobRunner |
Notable Patterns and Implementation Details
Migration validation before apply. Before calling
migrator.Update(), Job compares the database’s applied migration history (GetDatabaseMigrations) against the local code migrations (GetLocalMigrations). A mismatch throws InvalidOperationException, preventing an out-of-order or corrupt migration from being applied silently.Microsoft Entra ID (AAD) token refresh.
BaseDbMigrationContext.SetSqlConnectionAccessToken() checks SqlConnection.State before re-applying the access token. EF6’s DbMigrator may internally close and reopen connections, so the token must be refreshed to avoid authentication failures on reconnect.SQL script logging. Before executing,
Job uses MigratorScriptingDecorator to generate and log the full T-SQL that will be applied. This produces an audit trail in Application Insights / the job log without requiring a separate dry-run step.