JSON Columns
Starting with Weasel 8.11.1, the EF Core integration supports JSON column mappings defined via OwnsOne().ToJson(). This was previously silently ignored, causing JSON columns to be missing from Weasel's schema model (GitHub issue #232).
How It Works
When EF Core maps a complex property to a JSON column using ToJson(), Weasel detects this during table mapping by iterating each entity type's navigations. For each navigation whose target entity type returns true from IsMappedToJson(), Weasel:
- Reads the column name via
GetContainerColumnName(). - Reads the column type via
GetContainerColumnType(), falling back to the provider's own JSON store type when the model does not name one --jsonbon PostgreSQL,nvarchar(max)on SQL Server,TEXTon MySQL and SQLite,CLOBon Oracle (Migrator.DefaultJsonColumnType). The fallback used to be the literaljsonbon every provider, which produced invalid DDL anywhere but PostgreSQL (weasel#628). - Sets nullability based on whether the navigation's foreign key is marked as required.
Complex Properties Without ToJson()
A ComplexProperty that is not ToJson() is table-split: its members become ordinary columns of the owner's table, not a JSON container. Those are mapped too -- see Table Mapping. The two shapes can coexist on one entity.
EF Core Configuration
Define a JSON column using ComplexProperty with ToJson():
public class OrderDbContext : DbContext
{
public OrderDbContext(DbContextOptions<OrderDbContext> options) : base(options)
{
}
public DbSet<Order> Orders { get; set; } = null!;
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Order>(entity =>
{
entity.ToTable("orders", "myschema");
entity.HasKey(x => x.Id);
entity.Property(x => x.Id).HasColumnName("id");
entity.Property(x => x.Status).HasColumnName("status");
entity.OwnsOne(x => x.ShippingAddress, b =>
{
b.ToJson("shipping_address");
});
});
}
}The resulting Weasel table will include three columns:
id-- primary keystatus-- text columnshipping_address--jsonbcolumn, non-nullable (becauseIsRequired()was called)
Column Type
The column type defaults to jsonb for PostgreSQL. If EF Core specifies a different container column type via its metadata, that type is used instead. For SQL Server, this would typically be nvarchar(max).
Nullability
The JSON column's nullability is determined by the navigation's foreign key IsRequired setting:
b.IsRequired()-- column is NOT NULL- No
IsRequired()call -- column allows NULL
Owned Types Exclusion
Owned entity types (those configured via OwnsOne() or OwnsMany()) are excluded from GetEntityTypesForMigration() since they do not produce their own tables. This fix was added in Weasel 8.11.2 to address GitHub issue #234, which caused errors when owned types were incorrectly treated as standalone tables.
Migration Example
await using var migration = await serviceProvider.CreateMigrationAsync(dbContext, ct);
// The migration will include the JSON column in the table definition.
// If the column was previously missing (pre-8.11.1), the delta detection
// will flag it as a new column to add.
if (migration.Migration.Difference != SchemaPatchDifference.None)
{
await migration.ExecuteAsync(AutoCreate.CreateOrUpdate, ct);
}