Skip to content

Extension Methods

Each Weasel provider ships a SchemaObjectsExtensions class with convenience methods that make it easy to create, drop, migrate, and apply changes to individual schema objects using a single method call. These extensions wrap the delta detection and DDL generation pipeline behind simple async APIs.

SchemaObjectsExtensions

Every provider (Weasel.Postgresql, Weasel.SqlServer, Weasel.Oracle, Weasel.Sqlite) defines its own parallel set of these extension methods, each typed to the provider's connection class.

ApplyChangesAsync

Detects differences between the configured schema object and the actual database, then applies any needed DDL:

cs
// PostgreSQL
await pgTable.ApplyChangesAsync(npgsqlConnection);

// SQL Server
await ssTable.ApplyChangesAsync(sqlConnection);

// SQLite
await sqliteTable.ApplyChangesAsync(sqliteConnection);

snippet source | anchor

This is the most common method for keeping a single object in sync with the database. It runs the full detect-and-apply cycle.

CreateAsync

Generates and executes only the creation DDL, without checking whether the object already exists:

cs
// PostgreSQL
await pgTable.CreateAsync(npgsqlConnection);

// SQL Server
await ssTable.CreateAsync(sqlConnection);

snippet source | anchor

Use this when you know the object does not exist yet (e.g., during initial setup or testing).

DropAsync

Generates and executes the drop DDL:

cs
// PostgreSQL
await pgTable.DropAsync(npgsqlConnection);

// SQL Server
await ssTable.Drop(sqlConnection);

snippet source | anchor

MigrateAsync

Creates or updates the object based on delta detection, respecting an AutoCreate policy:

cs
// PostgreSQL -- defaults to AutoCreate.CreateOrUpdate
bool changed = await table.MigrateAsync(npgsqlConnection);

// With explicit policy
changed = await table.MigrateAsync(
    npgsqlConnection,
    autoCreate: AutoCreate.CreateOnly
);

snippet source | anchor

Returns true if any changes were applied, false if the object was already up to date. You can also migrate an array of objects together:

cs
var objects = new ISchemaObject[] { usersTable, ordersTable, sequence };
bool changed = await objects.MigrateAsync(sqlConnection);

snippet source | anchor

EnsureSchemaExists

Creates a database schema if it does not already exist (PostgreSQL and SQL Server):

cs
// PostgreSQL
await npgsqlConnection.EnsureSchemaExists("myapp");

// SQL Server
await sqlConnection.EnsureSchemaExists("myapp");

snippet source | anchor

SQLite does not need this method because it only supports the built-in main and temp schemas.

Full PostgreSQL Example

cs
await using var dataSource = NpgsqlDataSource.Create(connectionString);
await using var conn = await dataSource.OpenConnectionAsync();

// Ensure the schema exists
await conn.EnsureSchemaExists("myapp");

// Define a table
var table = new Weasel.Postgresql.Tables.Table(new PostgresqlObjectName("myapp", "people"));
table.AddColumn<int>("id").AsPrimaryKey();
table.AddColumn<string>("name").NotNull();
table.AddColumn<string>("email");

// Apply changes -- creates the table if missing, updates if changed
await table.ApplyChangesAsync(conn);

snippet source | anchor

Full SQL Server Example

cs
await using var conn = new SqlConnection(connectionString);
await conn.OpenAsync();

await conn.EnsureSchemaExists("myapp");

var table = new Weasel.SqlServer.Tables.Table(new SqlServerObjectName("myapp", "people"));
table.AddColumn<int>("id").AsPrimaryKey();
table.AddColumn<string>("name").NotNull();
table.AddColumn<string>("email");

await table.ApplyChangesAsync(conn);

snippet source | anchor

Full SQLite Example

cs
await using var conn = new SqliteConnection("Data Source=myapp.db");
await conn.OpenAsync();

// Apply PRAGMA settings for performance
var pragmas = new SqlitePragmaSettings
{
    JournalMode = JournalMode.WAL,
    ForeignKeys = true
};
await pragmas.ApplyToConnectionAsync(conn);

var table = new Weasel.Sqlite.Tables.Table("people");
table.AddColumn<int>("id").AsPrimaryKey().AutoIncrement();
table.AddColumn<string>("name").NotNull();
table.AddColumn<string>("email");

await table.ApplyChangesAsync(conn);

snippet source | anchor

CommandBuilder Extensions

Beyond schema objects, Weasel also provides extensions on CommandBuilderBase for executing commands:

MethodPurpose
ExecuteNonQueryAsync()Execute the command without reading results.
ExecuteReaderAsync()Execute and return a DbDataReader.
FetchListAsync<T>()Execute, read all rows, and materialize a List<T>.

These are used internally by Weasel's migration infrastructure and are available for your own database operations.

Provider Parity

Each provider implements the same set of extension methods with the same signatures (adjusted for connection type). This means switching providers requires only changing the using directive and connection type -- the calling code stays the same.

ExtensionPostgreSQLSQL ServerOracleSQLite
ApplyChangesAsyncYesYesYesYes
CreateAsyncYesYesYesYes
DropAsyncYesYesYesYes
MigrateAsyncYesYesYesYes
EnsureSchemaExistsYesYesNoNo

Released under the MIT License.