Columns and data types

Type, size, precision, nullability, defaults, identity and collation are explicit column attributes.

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

Explicit table and column steps

Create.Column(name).OnTable(table) and Alter.Column(name).OnTable(table) select the table before exposing type and column options. Delete.Column(name).FromTable(table) completes a removal. For a complete Column model use Create.Column(definition).OnTable(table) or Alter.Column(definition).OnTable(table); the definition is copied. Every named fluent column requires As... or OfType(...) before execution.

Table columns, added columns and altered columns share the same options, including AsGuid, AsBoolean, AsDecimal(precision, scale), AsDate, AsDateTime and AsDateTime2. AsDateTime maps to DbType.DateTime; AsDateTime2 maps to DbType.DateTime2. OfType(DbType) and OfType(MigratorDbType) remain available for other types. Nullability defaults to nullable.

Add and remove a column

Column builders take column name followed by table name. Classic AddColumn takes table name first. New nullable columns accept existing rows without a backfill. A required column usually needs a compatible default or a staged data migration.

Add an optional email address

Classic

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

Fluent

migration.Create.Column("Email").OnTable("Users").AsString(320).Nullable();

Inside Up() / BuildUp(MigrationBuilder migration)

Remove the email column

Classic

Database.RemoveColumn("Users", "Email");

Fluent

migration.Delete.Column("Email").FromTable("Users");

Inside Up() / BuildUp(MigrationBuilder migration)

Precision and defaults

For decimal values specify precision and scale. In a Column constructor an integer after the type is the size, not a numeric default. Set DefaultValue explicitly to avoid overload ambiguity. Plain strings are values; trusted SQL expressions use RawSql.Insert.

An amount with four decimal places

Classic

Database.AddColumn("Orders", new Column("Amount", DbType.Decimal)
{
    Precision = 12, Scale = 4, IsNullable = false, DefaultValue = 0m
});

Fluent

migration.Create.Column("Amount").OnTable("Orders").OfType(DbType.Decimal)
    .WithPrecision(12, 4).NotNullable().WithDefaultValue(0m);

Inside Up() / BuildUp(MigrationBuilder migration)

Time of day and durations

Use TimeOnly for time-of-day values and TimeSpan for intervals. A TimeSpan is a duration, including negative and multi-day values, so a TimeSpan default on a Time column is rejected. PostgreSQL and Oracle have native intervals; SQLite, SQL Server and MySQL/MariaDB store intervals as signed .NET ticks.

Clock time and elapsed time

Classic

Database.AddTable("Jobs",
    new Column("RunAt", DbType.Time) { DefaultValue = new TimeOnly(9, 30) },
    new Column("Elapsed", MigratorDbType.Interval) { DefaultValue = TimeSpan.Zero });

Fluent

migration.Create.Table("Jobs")
    .WithColumn("RunAt").OfType(DbType.Time).WithDefaultValue(new TimeOnly(9, 30))
    .WithColumn("Elapsed").OfType(MigratorDbType.Interval).WithDefaultValue(TimeSpan.Zero);

Inside Up() / BuildUp(MigrationBuilder migration)

Database storage differs

SQLite does not enforce declared string lengths or decimal precision. UInt64 values above Int64.MaxValue are rejected there. Oracle character empty strings become NULL; Informix and Sybase have their own trimming and range behavior. Consult the type support and boundary matrix for supported mappings and live-test scope. A shared DbType does not imply identical native storage.