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.
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.
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.
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.