C# and .NET First Verification
The first verification must execute through an ADO.NET provider and reopen the database. A successful generated-library build is necessary but not sufficient.
1. Contract and build
dotnet build -p:UseSharedCompilation=false
dotnet test -p:UseSharedCompilation=false
rg 'Purpose\(|ExecuteForListAsync|ExecuteEntitiesForListAsync' generated
Confirm execution receives only UserContext, and the terminal exists only on the
executable wrapper returned by Purpose.
2. SQLite integration
Use a unique database path. Initialize a trusted context with Microsoft.Data.Sqlite,
ensure schema, save one audited entity, query it, dispose connections, create a new
context, and query again.
[Fact]
public async Task PersistsAndReloadsARecord()
{
await using var fixture = await SqliteFixture.CreateAsync();
var ctx = fixture.Context;
var order = Q.CustomerOrders().Comment("Create verification order")
.Purpose("Verify SQLite persistence").NewEntity(ctx);
order.UpdateOrderNumber("VERIFY-10001");
await order.AuditAs("Create verification fixture").SaveAsync(ctx);
var rows = await Q.CustomerOrders().Comment("Read verification order")
.WithOrderNumberContaining("VERIFY-10001").Purpose("Verify persisted result")
.ExecuteEntitiesForListAsync(ctx);
Assert.Single(rows);
}
Replace illustrative names with the generated contract. Add a reconnect assertion.
3. Negative gates
Prove missing comment/purpose, uninitialized context, missing AuditAs, stale version,
unknown dynamic fields/operators, forbidden sorts, invalid ranges/offset/page sizes,
and trusted-context override attempts are rejected. Compile-time absence of terminals
is preferable where type state applies; runtime cases must throw explicit exceptions.
4. Provider SQL
Capture a masked trace for stable pagination, bound parameters, native
COUNT/SUM/GROUP BY, and partition/window per-parent Top-N. Rows, record count,
facets, and total must share one normalized active filter.
After SQLite, qualify each intended ADO.NET provider independently. SQL Server support is Feature-level only after the same semantic and governance suite passes; loading an ADO.NET assembly alone is not evidence.
5. Optimistic locking and audit
Load the same entity twice, save the first update with an audit reason, and assert the second save fails as stale. Verify both the immutable runtime mutation event and the separate masked application audit sink.
6. Regeneration
Add a model field, regenerate from scratch, rebuild and rerun tests. Record SDK, generator/runtime/provider versions, model hash, commands, exit codes, native response, and masked SQL trace.