Dapper works today

The first live consumer of the provider, and the gate that keeps it honest: Dapper talks to IDbConnection and nothing else, so a flow that works here works for any caller shaped the same way. This is the provider's gate test, not an example invented for the docs.

using H2Sharp.Data;

using IDbConnection con = new H2Connection("jdbc:h2:mem:demo");
con.Open();

_ = con.Execute("DROP TABLE IF EXISTS PERSON");
_ = con.Execute("CREATE TABLE PERSON(ID INT PRIMARY KEY, NAME VARCHAR(100) NOT NULL, AGE INT)");

int inserted = con.Execute(
    "INSERT INTO PERSON(ID, NAME, AGE) VALUES (@Id, @Name, @Age)",
    new Person { Id = 1, Name = "Ada", Age = 36 });

var rows = con.Query<Person>("SELECT ID, NAME, AGE FROM PERSON ORDER BY ID").AsList();
int updated = con.Execute(
    "UPDATE PERSON SET AGE = @Age WHERE ID = @Id", new { Id = 1, Age = 37 });
int count   = con.QuerySingle<int>("SELECT COUNT(*) FROM PERSON");
con.Execute("DELETE FROM PERSON WHERE ID = @Id", new { Id = 1 });
Gate (phase 8) — closed twice over. DapperSmokeTests: open, create, insert, update, select (repeat after the update on purpose), scalar path, delete. Plus ParametersAreNotConcatenatedIntoTheText: the statement keeps its @Id placeholders whatever the value is, so the provider is not a SQL-injection vector. And the inherited AdoNet.Specification.Tests suite is 293 of 293 green.

Dapper's own IDbTransaction support works too — BeginTransaction hands out a real transaction over the engine's own one.

Why this test and not another

Async (OpenAsync, ExecuteAsync, QueryAsync) is available on the provider; the gate test drives the synchronous surface.