Entity Framework Core Provider
CSharpDB.EntityFrameworkCore is an embedded-only Entity Framework Core 10 provider built on top of CSharpDB.Data. Use standard EF Core DbContext, migrations, change tracking, and LINQ patterns against local CSharpDB databases.
This guide documents the provider's supported behavior, current limits, and production guidance.
Install
dotnet add package CSharpDB.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.Design
Microsoft.EntityFrameworkCore.Design is recommended in the application project so dotnet ef can run design-time commands cleanly.
Basic Usage
Configure your context with UseCSharpDb(...).
using CSharpDB.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
public sealed class BloggingContext : DbContext
{
private readonly string? _connectionString;
public BloggingContext(string databasePath)
=> _connectionString = $"Data Source={databasePath}";
public BloggingContext(DbContextOptions<BloggingContext> options)
: base(options)
{
}
public DbSet<Blog> Blogs => Set<Blog>();
public DbSet<Post> Posts => Set<Post>();
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured && _connectionString is not null)
optionsBuilder.UseCSharpDb(_connectionString);
}
}
public sealed class Blog
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public List<Post> Posts { get; set; } = [];
}
public sealed class Post
{
public int Id { get; set; }
public int BlogId { get; set; }
public string Title { get; set; } = string.Empty;
public Blog Blog { get; set; } = null!;
}
Then use EF Core as usual.
await using var db = new BloggingContext("blogging.db");
await db.Database.EnsureCreatedAsync();
db.Blogs.Add(new Blog
{
Name = "Engineering",
Posts = [new Post { Title = "Hello from CSharpDB EF Core" }]
});
await db.SaveChangesAsync();
var blogs = await db.Blogs
.Include(blog => blog.Posts)
.OrderBy(blog => blog.Name)
.ToListAsync();
Existing Connections and In-Memory Databases
You can pass an existing CSharpDbConnection. This is required for a private :memory: database because the database lives as long as the connection stays open.
using CSharpDB.Data;
using CSharpDB.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
await using var connection = new CSharpDbConnection("Data Source=:memory:");
await connection.OpenAsync();
var options = new DbContextOptionsBuilder<BloggingContext>()
.UseCSharpDb(connection)
.Options;
await using var db = new BloggingContext(options);
await db.Database.EnsureCreatedAsync();
Provider-created file connections enable pooling unless the
connection string explicitly sets Pooling=false. EF Core can continue
its normal logical open/close pattern while CSharpDB retains one warm embedded
engine. Logical close rolls back unfinished transactions and clears
session-scoped temporary state; CSharpDbConnection.ClearPool and
ClearAllPools perform the physical close and WAL cleanup.
Explicit Transactions
SaveChanges, commit, and rollback work inside explicit EF Core transactions. CSharpDB does not implement transaction savepoints, so the provider advertises SupportsSavepoints == false and EF Core skips its automatic pre-SaveChanges savepoint.
await using var transaction = await db.Database.BeginTransactionAsync();
db.Blogs.Add(new Blog { Name = "Transactional" });
await db.SaveChangesAsync();
await transaction.CommitAsync();
CreateSavepoint, RollbackToSavepoint, and ReleaseSavepoint calls throw NotSupportedException.Supported ASP.NET Core Identity Configuration
Provider integration tests cover Identity schema v1 with integer user and role keys. Configure that exact model explicitly.
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
public sealed class AppUser : IdentityUser<int>;
public sealed class AppIdentityContext(
DbContextOptions<AppIdentityContext> options)
: IdentityDbContext<AppUser, IdentityRole<int>, int>(options)
{
protected override Version SchemaVersion => new(1, 0);
}
builder.Services.AddDbContext<AppIdentityContext>(options =>
options.UseCSharpDb(
builder.Configuration.GetConnectionString("CSharpDB")!));
builder.Services
.AddIdentity<AppUser, IdentityRole<int>>()
.AddEntityFrameworkStores<AppIdentityContext>();
The tested workflows cover the seven schema-v1 tables, users, roles, memberships, claims, external logins, tokens, persistence across reopen, cascade cleanup, concurrency stamps, transaction rollback, and cancellation.
IdentityDbContext<TUser>, Identity schema versions 2 and 3, passkeys, and unlisted store APIs remain unsupported. In particular, the standard string-key role-membership join is outside the provider's bounded integer-key join surface and reports CDBEF1007.Embedded Storage Tuning
The EF Core provider can pass embedded engine tuning down into the CSharpDbConnection it creates. Use named presets and embedded open modes when you want discoverable, compile-checked settings.
using CSharpDB.Data;
using CSharpDB.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
var options = new DbContextOptionsBuilder<BloggingContext>()
.UseCSharpDb(
"Data Source=blogging.db",
csharpdb =>
{
csharpdb.UseStoragePreset(CSharpDbStoragePreset.WriteOptimized);
csharpdb.UseEmbeddedOpenMode(CSharpDbEmbeddedOpenMode.HybridIncrementalDurable);
})
.Options;
Use full engine options when you need exact storage composition.
using CSharpDB.Engine;
using CSharpDB.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
var directOptions = new DatabaseOptions()
.ConfigureStorageEngine(builder => builder.UseWriteOptimizedPreset());
var options = new DbContextOptionsBuilder<BloggingContext>()
.UseCSharpDb(
"Data Source=blogging.db",
csharpdb => csharpdb.UseDirectDatabaseOptions(directOptions))
.Options;
Provider Builder Methods
UseDirectDatabaseOptions(DatabaseOptions)UseHybridDatabaseOptions(HybridDatabaseOptions)UseStoragePreset(CSharpDbStoragePreset)UseEmbeddedOpenMode(CSharpDbEmbeddedOpenMode)
Explicit DirectDatabaseOptions override Storage Preset. Explicit HybridDatabaseOptions override Embedded Open Mode. When EF Core is given an existing CSharpDbConnection, provider builder tuning is validated against that connection instead of mutating it.
For the full ADO.NET and EF Core tuning surface, see ADO.NET and EF storage tuning notes.
Migrations
For file-backed databases, the normal EF Core design-time workflow is supported.
dotnet ef migrations add InitialCreate
dotnet ef database update
dotnet ef migrations script
dotnet ef migrations script --idempotent
CSharpDB.EntityFrameworkCore.Tools package can compile a restored migration chain, inspect generated provider SQL, and optionally execute the supported chain against tool-owned in-memory scratch databases. See EF Core migration chain analysis for the command and evidence boundary.Database.Migrate() is supported for file-backed databases. EnsureCreated() is supported for file-backed and private in-memory databases. Migrations use the standard __EFMigrationsHistory table plus a simple __EFMigrationsLock row to serialize concurrent migration runs across processes. Idempotent scripts guard migration commands with history-table checks, so one script can be applied to empty, partially migrated, or current databases.
sys.foreign_keys for its stored name and use that name in a one-time migration. New 4.2.0 schemas preserve EF constraint names.ClientSetNull behavior is supported when at least one dependent FK property is nullable, including mixed-nullability composite keys. EF clears the nullable components before deleting a tracked principal. The generated database foreign key remains restrictive, so a dependent that is not tracked still blocks the delete. Required ClientSetNull relationships and database-side DeleteBehavior.SetNull remain unsupported.TEXT and composite INTEGER/TEXT logical primary keys support standalone add/drop migrations. Adding a physical single-INTEGER primary key to populated data validates non-NULL uniqueness, makes those values the physical row IDs, and atomically rebuilds ready ordinary/unique SQL, constraint-owned, and foreign-key-support indexes. Full-text, collection, and non-ready indexes reject the operation before mutation. EF drops use DROP CONSTRAINT with the exact key name. Use raw ALTER TABLE ... DROP PRIMARY KEY only for a legacy unnamed key. Dropping a primary key preserves NOT NULL; dropping a physical INTEGER key also ends its identity role. Adds reject existing nulls or duplicates without leaving key/index metadata, and drops are blocked when an inbound foreign key has no equivalent unique candidate.INTEGER to REAL changes accept values in the exactly representable ±253 range; the reverse accepts only finite, integral signed 64-bit values. TEXT columns can change among supported collations or return to default BINARY. Ready ordinary and unique SQL indexes that inherit the column collation are rebuilt atomically with the table; explicit-collation and unrelated indexes retain their roots. Row IDs are preserved, and checks plus affected uniqueness are revalidated. Key constraints, foreign keys, full-text/collection dependencies, views on the table, table-owned triggers, cross-table triggers that reference the column, and applicable validation rules remain blocked. Compound default/type/collation/nullability commands must remain in one migration transaction so a later failure restores the original table and index roots.Exact Decimal Foundation
decimal and nullable decimal properties use provider-owned scaled INTEGER storage without an application value converter. The default is decimal(18, 2); precision must be from 1 through 18, and scale must be from 0 through precision. Configure other supported facets with HasPrecision(precision, scale).
modelBuilder.Entity<Invoice>()
.Property(invoice => invoice.Amount)
.HasPrecision(18, 4);
Round trips, nullable values, parameters used with one facet mapping, equality/range comparisons, ordering, and ordinary indexes remain exact. Values with excess fractional digits are rejected instead of rounded, and values outside the configured precision fail as overflow. Raw SQL sees the scaled representation: 12.3400 at scale 4 is stored as 123400.
Sum/Average/Min/Max—are not yet supported. Decimal collection/subquery Contains, cross-facet parameter reuse, comparisons with application-converter decimal mappings, and model-mapped functions with decimal parameters or returns are also rejected. Unsafe query expressions fail before command dispatch with CDBEF1006. Use HasPrecision(precision, scale), not a custom decimal store type, for the provider-owned mapping.When calling IMigrationsSqlGenerator directly with a hand-authored AddPrimaryKeyOperation, pass the target model. A low-level call with model: null does not carry enough column metadata to identify a decimal mapping.
Database-Generated RowVersion
CSharpDB supports one nonnullable byte[] property per table configured with the standard [Timestamp] attribute or fluent IsRowVersion() API.
using System.ComponentModel.DataAnnotations;
public sealed class Document
{
public int Id { get; set; }
public string Contents { get; set; } = string.Empty;
[Timestamp]
public byte[] RowVersion { get; set; } = null!;
}
The provider creates the column as BLOB ROWVERSION. The engine initializes an opaque eight-byte token at revision 1, advances it on every successful UPDATE, and returns the generated value to EF after inserts and updates. Raw SQL, trigger-issued updates, and updates that leave all other values unchanged advance the token too. EF includes the original token in update and delete predicates, so stale tracked writes throw DbUpdateConcurrencyException.
rowversion, they are not drawn from one database-wide monotonically increasing counter. Explicit insert or update assignments to the rowversion column are rejected. Rowversion properties cannot participate in keys, foreign keys, or indexes, and cannot define a value converter, default, or computed SQL.EnsureCreated, migrations, and generated scripts is supported. Standalone migrations that add rowversion to an existing table or alter a column into or out of rowversion remain explicit rejections.LINQ Translation
The provider supports a deliberately bounded server-side LINQ surface. Basic support includes Where, ordering, Skip/Take, scalar projections, Single, Any, Count, non-decimal constant/parameter collection Contains, and simple Include queries.
String members and methods
string.Length- Parameterless
ToLower(),ToLowerInvariant(),ToUpper(), andToUpperInvariant() - Parameterless
Trim(),TrimStart(), andTrimEnd() Replace(string, string)Substring(start)andSubstring(start, length); the provider converts .NET's zero-based start index to CSharpDB's one-based SQL indexContains(string)with ordinal semanticsStartsWith(string, StringComparison.Ordinal),EndsWith(string, StringComparison.Ordinal), andContains(string, StringComparison.Ordinal)when the comparison argument is a literalEF.Functions.Like(match, pattern)andEF.Functions.Like(match, pattern, escape)over one directly mapped, converter-freeTEXTproperty
Both culture-sensitive and invariant CLR casing methods map to CSharpDB LOWER/UPPER. They therefore use invariant server semantics, not the application's CurrentCulture.
Ordinal string predicates require provider-owned, converter-free TEXT mappings. Search text may be a constant or captured parameter, including an empty string, and is treated literally: %, _, and backslash are not wildcard or escape syntax. The dedicated translations are case-sensitive and propagate SQL NULL.
EF.Functions.Like intentionally uses SQL pattern syntax: % matches zero or more UTF-16 code units and _ matches one UTF-16 code unit. The match must be one direct converter-free TEXT property, while the pattern may be a constant or captured string, including null. CSharpDB LIKE is invariant case-insensitive. The three-string overload requires a compile-time, non-null, one-UTF-16-code-unit escape literal other than %. A positive nullable LIKE predicate excludes SQL NULL; EF Core's normal null compensation makes a negated nullable predicate include NULL rows. SQLite parity covers bounded ASCII patterns; Unicode casing and supplementary-character wildcard behavior are provider-specific.
Date and time components
DateTime.Year,Month,Day,Hour,Minute, andSecondDateOnly.Year,Month, andDayTimeOnly.Hour,Minute, andSecond
Double-precision math
For finite REAL-mapped values, the provider translates Math.Abs(double), Math.Round(double), Math.Floor(double), Math.Ceiling(double), Math.Truncate(double), and Math.Sign(double) in predicates, projections, and ordering. Translated functions propagate SQL NULL, and Math.Round(double) uses midpoint-to-even semantics.
Scalar numeric aggregates
The supported aggregate slice covers Count, LongCount, simple and bounded-shape Any, Sum over int, double, and nullable double, Average over double and nullable double, and Min/Max over int, double, and nullable double. Filtered, empty, and all-NULL cases are cross-checked against SQLite.
Bounded direct inner and left joins
One explicit Queryable.Join or no-comparer Queryable.LeftJoin is supported between sources that normalize to direct mapped entity roots. The outer root may have an optional Where; the inner root must remain unfiltered because EF Core otherwise emits a derived-table join target that CSharpDB's current table-reference grammar does not accept. Each side must use one direct nonnullable int, long, or int/long-backed enum property backed by INTEGER with compatible provider mappings. Supported scalar or entity result projections and post-join filtering, ordering, and Skip/Take include self-joins.
LeftJoin preserves an outer row when no inner row matches. The unmatched inner entity and reference-type members materialize as null; project unmatched inner value-type members to nullable CLR types, for example PostId = (int?)post!.Id. This explicit nullable projection prevents SQL NULL from being interpreted as a value type's CLR default.
CDBEF1007 for Join or CDBEF1008 for LeftJoin. Comparer overloads, the classic GroupJoin/SelectMany/DefaultIfEmpty left-join pattern, standalone GroupJoin or SelectMany, RightJoin, and cross-join forms remain unsupported and report CDBEF1003.Terminal integer set operations
Exactly one terminal no-comparer Queryable.Concat, Queryable.Union, Queryable.Intersect, or Queryable.Except is supported when both branches remain direct mapped entity tables with optional filtering and each projects one compatible, converter-free INTEGER-backed int, long, or nullable equivalent. Concat preserves duplicates. The other three operators use distinct set semantics, including one SQL NULL set value where appropriate. Result order is unspecified; materialize before applying client-side ordering or transformations.
CDBEF1009. The comparer overloads of Union, Intersect, and Except remain unsupported and report CDBEF1003.Distinct numeric aggregates
The supported scalar shape is an optional Where, followed by selection of one directly mapped nonnullable int column, Distinct, and Count, LongCount, Sum, Min, or Max.
Average, nullable or non-int columns, configured value converters, ordering, row limits, predicates after Distinct, intervening operators, computed or composite selectors, casts, and derived sources are rejected with CDBEF1004 before command dispatch. Nullable Distinct().Count() and Distinct().LongCount() also cannot preserve LINQ's rule that a distinct NULL is counted once because SQL COUNT(DISTINCT column) ignores NULL.Grouped numeric aggregates
Direct single-table GroupBy supports an optional pre-filter and direct mapped Boolean, integral, enum, default-BINARY string, or nullable keys. Composite keys must use C# anonymous types or ValueTuple. Boolean key columns must contain canonical provider-written 0/1 storage. One grouped projection can contain direct keys plus bare Count/LongCount, Sum over int/double/nullable double, Average over double/nullable double, Min/Max over int/double/nullable double, and direct nonnullable-int Distinct variants for every listed aggregate except Average. Basic HAVING predicates, including aggregate IS NULL, and ordering by a directly projected key or aggregate are supported.
double, transformed, non-BINARY-collated, or configured-converter keys; aggregate value converters; element/result selector overloads; group materialization; raw group transforms; post-projection filtering, projection, distinct, limits, set, or join operations; nested grouping; predicate/CASE aggregates; casts; and broader types or shapes are rejected with CDBEF1005 before command dispatch.
StartsWith(string)/EndsWith(string), the Boolean/CultureInfo forms, non-ordinal or captured StringComparison modes, and character overloads. Transformed or configured-converter LIKE match expressions, row-derived patterns, and captured, empty, multi-character, or null escapes are also rejected. They fail before command dispatch with CDBEF1001 guidance. Plain Contains(string), the three literal-StringComparison.Ordinal overloads, and the bounded EF.Functions.Like forms above are supported. Non-decimal collection Contains over constants and parameters is also supported.
DateTimeOffset components; integral, decimal, MathF, precision-argument, midpoint-mode, and transcendental math overloads; long- and float-valued Sum/Average/Min/Max variants and other unsupported aggregate variants; broader distinct and grouped aggregate shapes; broader set-operation projections, mappings, nesting, chaining, and post-set composition; composite/chained/right/cross or derived-source joins; and correlated-query shapes remain outside the supported surface.
Unsupported-expression diagnostics
Unsupported expressions retain EF Core's InvalidOperationException and add stable provider guidance before a command is dispatched. Diagnostics identify the construct without adding parameter values.
| Code | Meaning |
|---|---|
CDBEF1001 | Unsupported CLR method |
CDBEF1002 | Unsupported CLR member |
CDBEF1003 | Recognized unsupported query operator, including TakeWhile, SkipWhile, set-operation comparer overloads, Join(comparer), LeftJoin(comparer), GroupJoin, SelectMany, DefaultIfEmpty, RightJoin, or ExecuteUpdate |
CDBEF1004 | Unsupported distinct aggregate shape |
CDBEF1005 | Unsupported grouped aggregate shape |
CDBEF1006 | Unsupported decimal operation outside the exact scaled-integer foundation |
CDBEF1007 | Unsupported inner-join shape outside the bounded direct-join surface |
CDBEF1008 | Unsupported left-join shape outside the bounded direct-join surface |
CDBEF1009 | Unsupported set-operation shape outside the bounded terminal direct-integer surface |
When client evaluation is intentional, apply selective supported filters first, then call AsEnumerable() explicitly before the unsupported portion. This makes the server/client boundary visible and avoids accidentally loading an entire table.
Supported Surface
| Area | Supported | Notes |
|---|---|---|
| Embedded runtime provider | Yes | No daemon or remote transports |
| File-backed databases | Yes | Primary supported runtime and migration mode |
| File connection pooling | Yes | Provider-created connections enable pooling by default; Pooling=false remains available for an explicit physical-close lifecycle |
Private :memory: runtime | Yes | Requires an open CSharpDbConnection |
EnsureCreated() | Yes | File-backed and private in-memory |
Database.Migrate() | Yes | File-backed only |
dotnet ef migrations add | Yes | Use the app project with Microsoft.EntityFrameworkCore.Design |
dotnet ef database update | Yes | File-backed only |
dotnet ef migrations script | Yes | Includes idempotent scripts guarded by __EFMigrationsHistory |
| CRUD + change tracking | Yes | Includes affected-row concurrency checks |
| Explicit transactions | Partial | SaveChanges, commit, and rollback are supported; savepoints are not |
| Database-generated rowversion | Partial | One nonnullable byte[] [Timestamp]/IsRowVersion() per table; runtime and initial table creation are supported, standalone add/alter migrations are not |
| Integer identity propagation | Yes | Single-column integer primary keys |
| Composite primary keys and indexes | Yes | Composite primary keys are emitted as table constraints; composite unique and non-unique indexes preserve declared column order |
| Standalone primary-key migrations | Partial | Named logical keys add/drop; physical INTEGER adds can rekey validated populated rows and supported relational indexes atomically; EF drops match the exact constraint name |
| Alternate keys and unique constraints | Yes | Named create-table constraints plus standalone add/drop migrations |
| Foreign keys | Partial | Named scalar/composite create/add/drop, primary or alternate-key targets, cascade/restrict behavior, and optional-relationship ClientSetNull; database-side SetNull is unsupported |
| Literal column defaults | Partial | HasDefaultValue(...) values that map to INTEGER, REAL, TEXT, BLOB, or NULL; computed/default SQL expressions remain unsupported |
| Check constraints | Partial | Create-table and standalone add/drop migrations for deterministic row-local expressions accepted by the engine |
AlterColumn | Partial | Literal default/nullability changes, exact dependency-free INTEGER/REAL rewrites, and TEXT collation changes with inherited ordinary/unique SQL-index rebuilding |
| Exact decimal mapping | Partial | Provider-owned scaled INTEGER storage for precision 1–18; exact round trips, parameters, comparisons, and ordering |
| Bounded LINQ/query subset | Partial | Basic operators plus bounded direct inner and left joins, terminal direct-integer set operations, and the string, EF.Functions.Like, temporal, finite-double math, scalar numeric aggregate, direct-column distinct aggregate, and direct single-table grouped aggregate translations listed above; unsupported methods, members, operators, set-operation shapes, aggregate shapes, and join shapes receive provider diagnostics |
| ASP.NET Core Identity | Partial | Identity schema v1 with IdentityUser<int> and IdentityRole<int> for the documented workflows |
| Supported CLR types | Yes | bool, integral types, enums, bounded exact decimal, double, float, string, Guid, DateTime, DateTimeOffset, DateOnly, TimeOnly, byte[] |
Current Limitations
- Provider-owned decimal mapping does not yet support keys, defaults, generated values, computed decimal expressions, or precision/scale-changing migrations.
- Complex properties are rejected until their flattened column mappings are supported.
ExecuteUpdateis rejected until assignment conversions and decimal facets are supported.- Direct
Joinand no-comparerLeftJoinare limited to one nonnullableint,long, orint/long-backed enum key; filtered inner sources, derived/composite/chained joins, comparer overloads, classicGroupJoin/SelectMany/DefaultIfEmptyleft joins,RightJoin, and cross joins remain unsupported. - Set operations are limited to one terminal
Concat,Union,Intersect, orExceptover compatible direct converter-freeINTEGERint/longcolumn projections; branch ordering or limits, broader projections and mappings, comparer overloads, nested/chained operations, and server composition after the operation remain unsupported. - Optional relationships support EF's client-side
ClientSetNull; database-sideDeleteBehavior.SetNull/ON DELETE SET NULLremains unsupported. - Schemas are unsupported in runtime and migrations.
- Computed columns and
DefaultValueSqlare unsupported. - Rowversion is limited to one nonnullable
byte[]property created with its table; standalone add/alter rowversion migrations are unsupported. - All other string-search overloads—including default
StartsWith(string)/EndsWith(string), the Boolean/CultureInfoforms, non-ordinal or capturedStringComparisonmodes, and character overloads—plus transformed/configured-converterLIKEmatches, row-derivedLIKEpatterns, captured or invalidLIKEescapes, andDateTimeOffsetcomponent translation are unsupported. - Integral, decimal,
MathF, precision-argument, midpoint-mode, and transcendental math overloads are outside the supported translation surface. - Long- and float-valued
Sum/Average/Min/Maxvariants, integerAverage, textMin/Max, and broader distinct/grouped aggregate types and shapes remain outside the supported surface. - Physical
INTEGERprimary-key rekeying supports ready ordinary/unique SQL, constraint-owned, and foreign-key-support indexes; full-text, collection, and non-ready indexes are rejected. - Named shared-memory databases (
:memory:<name>) are rejected. - Endpoint, daemon, and non-direct transports are rejected.
- Transaction savepoints are unsupported. The provider reports that capability accurately so ordinary explicit-transaction
SaveChangescalls do not issue savepoint SQL. - ASP.NET Core Identity is supported only for schema v1 with integer user and role keys; default string keys, schema versions 2 and 3, passkeys, and unlisted store APIs remain unsupported.
TEXT/BLOBtype conversions, lossy numeric conversions, numeric type changes on indexed/key/foreign-key columns, and collation changes involving key/foreign-key/full-text/collection dependencies require broader rewrite support.- Broad table-rebuild migration emulation is not implemented; unsupported operations fail explicitly.
DDL Surface
The migrations SQL generator currently supports CreateTable (including one BLOB ROWVERSION column, literal defaults, deterministic row-local checks, composite primary keys, alternate keys, named scalar/composite foreign keys, and column collations), DropTable, RenameTable, AddColumn, RenameColumn, DropColumn, composite CreateIndex, DropIndex, RenameIndex, standalone add/drop named check, unique, foreign-key, and bounded primary-key constraints (including populated single-INTEGER rekeying with supported relational-index rebuilding), and AlterColumn changes to literal defaults, nullability, exact numeric types, and text collations with inherited ordinary/unique SQL-index rebuilding. Standalone rowversion add/alter operations, broader primary-key rekeys, indexed numeric changes, key/FK/full-text/collection-dependent column rewrites, and nonnumeric type conversions remain explicit rejections.