Data · Types
Customers
The same CRUD shape as Catalog, aimed at the values that historically broke on a WASM
transport: a Guid public id, a DateOnly birth date, a
bool flag stored as INTEGER, and a decimal credit limit that keeps
its scale because it is compared through ef_compare, not floating point.
Fastest persistent tier. Real files in the origin private file system. Concurrent connections, no COOP/COEP.
Directory
Every customer, sorted by name. Click a row to edit it in the panel under the table, next to what each value becomes in the SQLite file.
DbUpdateException - see the snippet below.
| Name | Born | Credit | VIP | Actions |
|---|
Edit customer
Select a row, or create one.
What the values become
| Property | Stored as |
|---|---|
| PublicId | TEXT, 36-char Guid |
| DateOfBirth | TEXT yyyy-MM-dd |
| IsVip | INTEGER 0/1 |
| CreditLimit | TEXT, compared via ef_compare |
| CreatedUtc | TEXT, ISO 8601 |
Filtering on CreditLimit - a real decimal comparison in SQL, not in
the CLR - is on the SQL page.
_rows = await context.Customers
.AsNoTracking()
.OrderBy(c => c.DisplayName)
.ToListAsync();
// Insert: PublicId is a Guid the CLR generated, stored as TEXT and read back as a Guid.
context.Customers.Add(new Customer
{
DisplayName = "Ada Lovelace",
Email = "[email protected]",
DateOfBirth = new DateOnly(1980, 1, 1),
CreditLimit = 1_000m,
IsVip = true,
});
await context.SaveChangesAsync();The entity and its configuration
No browser-specific attributes, no converters bolted on for WASM. Precision and the unique index are declared once and apply on the server and in the tab alike.
public sealed class Customer
{
public int Id { get; set; }
public Guid PublicId { get; set; } = Guid.NewGuid();
public string DisplayName { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public DateOnly DateOfBirth { get; set; }
public bool IsVip { get; set; }
public decimal CreditLimit { get; set; }
public string Notes { get; set; } = string.Empty;
public DateTime CreatedUtc { get; set; } = DateTime.UtcNow;
}
// Precision travels with the model, not with the backend.
builder.Property(c => c.CreditLimit).HasPrecision(18, 2);
builder.HasIndex(c => c.Email).IsUnique();Handling a constraint failure
After a failed save the change tracker still holds the rejected entity, so the demo clears it before the next read - the same hygiene you would apply on a server. The inner exception carries SQLite's message and result code.