Use a Separate SQL Server Sequence for Each EF Core Table

A SQL Server table migrated from Oracle may generate its primary key from a named sequence instead of an identity column. EF Core must know which sequence belongs to each property; otherwise an insert can send no generated value and fail because the key column does not allow NULL.

Last updated: October 22, 2026.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Customer>()
        .Property(customer => customer.Id)
        .UseSequence("CustomerSeq", "dbo");

    modelBuilder.Entity<Order>()
        .Property(order => order.Id)
        .UseSequence("OrderSeq", "dbo");
}

Use the exact sequence and schema names that exist in SQL Server. This mapping tells the SQL Server provider to obtain generated values from the specified sequence when a new entity is added.

Use property-level sequence mapping

EF Core supports model-wide sequences through HasSequence(), but declaring a sequence alone does not connect it to a key property. The SQL Server provider offers UseSequence() for that property-level mapping. Configure each entity separately when the database has one sequence per table.

Do not replace this with UseHiLo() unless you deliberately want EF Core to reserve ranges of values. Hi-lo generation reduces database round trips but has different allocation behavior. Direct sequence mapping matches a schema in which SQL Server supplies the next sequence value for each insert.

Verify the existing database contract

Confirm that every sequence exists, its data type fits the key property, and the application login can use it. The official EF Core sequence documentation shows how migrations create sequences, while the SQL Server value-generation guide distinguishes sequences from other strategies. A database-first migration may already contain the sequence, so avoid creating a second one with a similar name.

Log the generated SQL during a test insert and verify that EF receives the generated key after SaveChanges(). Also test explicit imports separately: if an import must preserve historical IDs, do not mix that path with normal generated-key inserts. Keep the key property configured as generated on add rather than assigning zero or a placeholder value in application code.

For related design decisions, see when to use a composite primary key, SQL Server output parameters, and finding Query Store plans by index.

Related Web Cheat Sheet guides

Sergey Kornilov

Sergey Kornilov