Course contentsShow
← C#
Lesson 1039 of 1,90810. Entity Framework Core ModelingFree lesson

Value Generation Patterns

Implement database-side default values and sequence generation for unique identifier generation.

In this lesson, you will learn how to offload unique identifier generation to the database engine using default values and sequences to maintain consistency outside of your C# application logic.

Why Database-Side Generation?

While EF Core often generates IDs (like Guids) in your C# code, there are scenarios where you want the database to handle value generation. This is crucial for high-concurrency environments or when your database must ensure sequential integrity without relying on the application layer.

Using Default Values

If you have a column that should have a specific value (like a timestamp or a default status) when a row is inserted, you can use the .HasDefaultValue() method in your OnModelCreating configuration.

modelBuilder.Entity<Order>()
    .Property(o => o.CreatedDate)
    .HasDefaultValueSql("GETUTCDATE()");

By using HasDefaultValueSql, you pass the responsibility to the SQL provider, ensuring that even if another application writes directly to the table, the default value is applied correctly.

Sequence Generation

For scenarios requiring unique, incrementing numbers that are independent of a specific table’s identity column, you can use Database Sequences. A sequence is a database object that generates a numeric sequence according to your specifications.

First, define the sequence in your DbContext:

modelBuilder.HasSequence<int>("OrderNumberSequence")
            .StartsAt(1000)
            .IncrementsBy(1);

Then, link this sequence to a specific entity property so EF Core knows to fetch the next value from the database when saving changes:

modelBuilder.Entity<Order>()
    .Property(o => o.OrderNumber)
    .HasDefaultValueSql("NEXT VALUE FOR OrderNumberSequence");

When to use these?

  • Default Values: Use these for static fallbacks or database-server-calculated timestamps to keep domain entities clean.
  • Sequences: Use these when you need globally unique, incrementing identifiers across different tables or when you need to control the starting point and increment logic of your keys.

This approach keeps your C# entities focused on behavior while allowing the database to enforce structural integrity.

Key Takeaway: By utilizing HasDefaultValue and sequences within the Fluent API, you ensure that unique data generation is handled at the database level, providing robust, concurrency-safe values that remain consistent regardless of which application performs the insertion.