Schema inspection

Read the connected database before deciding what to change. Metadata is different from a model snapshot.

Examples use Classic and Fluent tabs. Your choice follows you through the manual.

Inspect tables and columns

Classic migrations read through Database. FluentMigration exposes Schema for queries and Context for the full provider API. A fluent authoring method runs before its queued operations: an inspection cannot see a table merely queued earlier in the same builder.

Add a column only when it is missing

Classic

if (!Database.ColumnExists("Users", "Email"))
    Database.AddColumn("Users", new Column("Email", DbType.String, 320));

Fluent

if (!Schema.Table("Users").ColumnExists("Email"))
    migration.Create.Column("Email").OnTable("Users").AsString(320);

Inside Up() / BuildUp(MigrationBuilder migration)

Read ordered constraints

GetColumns returns inferred column attributes, not primary/unique membership flags. It is obsolete because native types and defaults cannot be mapped back to exact .NET definitions; use migration history for the original definition. Read typed table constraints to retain ordered composite keys. Unique indexes remain index metadata. MySQL/MariaDB catalogs cannot distinguish every original unique-index versus UNIQUE-clause authoring choice.

Read table constraint definitions

Classic

var constraints = Database.GetTableConstraints("Users");
foreach (var constraint in constraints)
    Console.WriteLine(constraint.Name);

Fluent

var constraints = Schema.Table("Users").ConstraintDefinitions();
foreach (var constraint in constraints)
    Console.WriteLine(constraint.Name);

Inside Up() / BuildUp(MigrationBuilder migration)

Create a view

ViewField selects columns from a base table. The alternative IViewElement overload represents explicit columns and joins. View definitions are provider-dependent and outside SQL preview and automatic reversal. Write a provider-appropriate DROP VIEW statement in the reverse method, and manage dependent views when changing their underlying tables.

A projection over Users

Classic

Database.AddView("UserNames", "Users", new ViewField("Id"), new ViewField("Name"));

Fluent

migration.Create.View("UserNames").FromTable("Users")
    .WithFields(new ViewField("Id"), new ViewField("Name"));

Inside Up() / BuildUp(MigrationBuilder migration)

Reads and portability

Dispose readers and commands obtained from the provider. Fluent Schema.Query and Schema.Table(name).Select accept a reader callback and handle disposal. Use Schema.Table(name).SelectScalar(columns, where) for a scalar selection. Use provider quoting helpers for table and column identifiers separately: quoting a table may introduce schema qualification, which is not valid for a column expression.

Metadata fidelity depends on the provider. Unsupported readers throw instead of pretending that an empty schema was found. A successful existence check is not a full schema-drift report.