Table of Contents

Sequences and UUID generators

Server-side value generators: sequences advance and read, and UUID generators mint unique identifiers. Neither has a single portable spelling, because the providers do not offer the same set of operations. For sequences, PostgreSQL, MariaDB and SQL Server are supported today.

Operation PostgreSQL MariaDB SQL Server
Next value SqlFunctions.Postgres.nextval(seq) SqlFunctions.MySql.nextval(seq) / next_value_for(seq) SqlFunctions.SqlServer.next_value_for(seq) / nextval(seq)
Set the next value SqlFunctions.Postgres.setval(seq, value) SqlFunctions.MySql.setval(seq, value) —
Current value (session) SqlFunctions.Postgres.currval(seq) — —
Last value (session/connection) SqlFunctions.Postgres.lastval() SqlFunctions.MySql.lastval(seq) —

PostgreSQL

The sequence name is cast to regclass. The functions are part of the extended scalar library (SupportsExtendedScalarFunctions, PostgreSQL only):

C# SQL
SqlFunctions.Postgres.nextval(sequence) nextval(cast(sequence as regclass))
SqlFunctions.Postgres.setval(sequence, value) setval(cast(sequence as regclass), value)
SqlFunctions.Postgres.currval(sequence) currval(cast(sequence as regclass))
SqlFunctions.Postgres.lastval() lastval()
var next = dataContext.From<IComplexEntity>()
    .Select(e => SqlFunctions.Postgres.nextval("order_id_seq"))
    .First();

currval and lastval are session-scoped: they require the same connection that last advanced the sequence.

MariaDB

The sequence name is taken as a string and emitted as an identifier (not a quoted literal), so SqlFunctions.MySql.next_value_for("order_seq") renders next value for order_seq:

C# SQL
SqlFunctions.MySql.next_value_for(sequence) next value for sequence
SqlFunctions.MySql.nextval(sequence) nextval(sequence)
SqlFunctions.MySql.setval(sequence, value) setval(sequence, value)
SqlFunctions.MySql.lastval(sequence) lastval(sequence)
var rows = dataContext.From<IOrderEntity>()
    .Select(x => new { Id = SqlFunctions.MySql.nextval("order_seq") })
    .ToList();

These names are MariaDB-only: MySQL, PostgreSQL, SQL Server, SQLite, ClickHouse and the in-memory context reject them with NotSupportedException. lastval reads the connection's last generated value.

MariaDB sequence functions and their availability are listed in the MariaDB catalogue.

SQL Server

SQL Server reads a sequence through NEXT VALUE FOR, exposed by SqlFunctions.SqlServer.next_value_for(sequence) and its alias nextval(sequence) (both return CLR long). The name must be a constant string naming one object, written as either one component (name) or two (schema.name); each component is bracket-quoted separately with an embedded ] doubled, so raw name text cannot escape the identifier:

C# SQL
SqlFunctions.SqlServer.next_value_for(sequence) next value for [sequence]
SqlFunctions.SqlServer.next_value_for("dbo.sequence") next value for [dbo].[sequence]
SqlFunctions.SqlServer.nextval(sequence) next value for [sequence]
var rows = dataContext.From<IOrderEntity>()
    .Select(x => new { Id = SqlFunctions.SqlServer.next_value_for("order_seq") })
    .ToList();

A non-constant or captured name (a column, a captured local, default/null) is rejected with NotSupportedException, and the name is never bound as a SQL parameter — it is an identifier, not a value. SQL Server has no session-scoped currval/lastval and no value-returning setval (its equivalent is the DDL ALTER SEQUENCE ... RESTART WITH), so only the next value is exposed. These names require a provider that reports them through ISqlDialect.SqlServerFunctions; every other provider rejects them. Tracked in #218.

UUID generators

SqlFunctions.Sql.gen_random_uuid() (random v4) and uuidv7() are cross-provider (UuidGenerators):

C# PostgreSQL SQL Server MySQL MariaDB ClickHouse SQLite
gen_random_uuid() gen_random_uuid() (13+) newid() — uuid_v4() (11.7+) generateUUIDv4() —
uuidv7() uuidv7() (18+, explicit version) — — uuid_v7() (11.7+) generateUUIDv7() —

On PostgreSQL, uuidv7() renders only when the context is configured with an explicit 18+ server version; a version below 18 or an unset version refuses the call at preparation with a plain NotSupportedException: The uuidv7 function is not supported by this provider. The v4 generator is never substituted and NULL is never returned; gen_random_uuid() (v4) keeps its existing PostgreSQL 13+ behaviour.

MySQL has only UUID() (v1) and SQLite has no UUID generator, so both reject the calls. On MariaDB both generators require an explicit server version 11.7 or later; an unversioned MariaDbDataContext refuses them with NotSupportedException, and UUID() (v1) is never substituted. These are server-side generators, evaluated per row by the database; Guid.NewGuid() is a client-side value and is not a substitute. SQL Server additionally exposes newsequentialid() (SqlFunctions.SqlServer.newsequentialid()), which is valid only as a column DEFAULT and not in an ordinary SELECT.

PostgreSQL also reads data back out of a stored UUID, on SqlFunctions.Postgres and gated per name by IScalarFunctions.Supports:

C# SQL Returns
SqlFunctions.Postgres.uuid_extract_timestamp(value) uuid_extract_timestamp(value) timestamptz (DateTime?) — NULL for a version-4 UUID or the nil UUID
SqlFunctions.Postgres.uuid_extract_version(value) uuid_extract_version(value) smallint (short?) — the embedded version, NULL for the nil UUID