Understanding Auto-increment and Value Generation in Entity Framework

Nov 27, 2025 · Programming · 8 views · 7.8

Keywords: Entity Framework | Primary Key Auto-generation | DatabaseGenerated | Value Generation Strategy | EF Core Configuration

Abstract: This technical article provides an in-depth analysis of primary key auto-generation mechanisms in Entity Framework. Through practical case studies, it explains why string-type primary keys cause insertion failures and demonstrates proper configuration using int-type keys. The article covers DatabaseGenerated annotations, value generation strategies, and includes comprehensive code examples for effective EF Core implementation.

Problem Context and Phenomenon Analysis

During Entity Framework Core application development, developers frequently encounter primary key generation failures when inserting entities. A typical scenario involves creating user entities through Web API with JSON data, where the system throws a "Cannot insert the value NULL into column 'Id'" exception despite explicitly annotating the entity class with [DatabaseGenerated(DatabaseGeneratedOption.Identity)] attribute.

In the specific case, the user entity is defined as follows:

public class User
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public string Id { get; set; }
    public string Username { get; set; }
    // Other properties...
}

When the client sends a JSON request without the Id field:

{Username:"Bob", FirstName:"Foo", LastName:"Bar", Password:"123", Headline:"Tuna"}

EF Core cannot automatically generate the primary key value, causing the database insertion operation to fail. However, if an Id value is explicitly provided in the request, the operation executes successfully.

Root Cause Investigation

The core issue lies in the matching between primary key data type selection and EF Core value generation strategy. According to EF Core official documentation, the value generation mechanism has different default behaviors for different data types:

In SQL Server databases, numeric primary keys usually map to IDENTITY columns, which support auto-increment functionality at the database level. String-type primary keys cannot directly map to auto-increment columns and require additional configuration for automatic value generation.

Solution Implementation

Based on problem analysis, the most direct solution is changing the primary key type from string to int:

public class User
{
    public int Id { get; set; }
    public string Username { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Password { get; set; }
    public string Headline { get; set; }
    // Navigation properties remain unchanged
}

After modification, EF Core automatically configures the Id property as an auto-incrementing primary key in the database, requiring no additional data annotations. In the controller, the same insertion code now works correctly:

[HttpPost]
public async Task<ActionResult<User>> PostUser(User user)
{
    _context.Users.Add(user);
    await _context.SaveChangesAsync();
    return CreatedAtAction(nameof(GetUser), new { id = user.Id }, user);
}

Advanced Configuration Options

For special scenarios requiring string primary keys, EF Core provides multiple value generation configuration methods:

Default Value Configuration

Configure property default values via Fluent API:

modelBuilder.Entity<User>()
    .Property(u => u.Id)
    .HasDefaultValueSql("NEWID()"); // For GUID generation in SQL Server

Computed Column Configuration

For scenarios requiring values computed from other columns:

modelBuilder.Entity<Person>()
    .Property(p => p.DisplayName)
    .HasComputedColumnSql("[LastName] + ', ' + [FirstName]");

Explicit Value Generation Control

Explicitly configure value generation using the ValueGeneratedOnAdd method:

modelBuilder.Entity<User>()
    .Property(u => u.Id)
    .ValueGeneratedOnAdd();

Associated Entity Synchronization

After modifying the primary key type, ensure all foreign key references in associated entities are synchronized. For example, change the UserId in the Connection entity to int type as well:

public class Connection
{
    public string ConnectionId { get; set; }
    public int UserId { get; set; } // Synchronously changed to int type
    public virtual User User { get; set; }
}

Best Practice Recommendations

  1. Primary Key Type Selection: Prefer numeric types (int, long) as primary keys for optimal automatic generation support
  2. Naming Conventions: Follow EF Core naming conventions, such as using Id or EntityName+Id as primary key property names
  3. Configuration Clarity: In complex scenarios, use Fluent API to explicitly configure value generation strategies, avoiding reliance on implicit conventions
  4. Testing Validation: After modifying primary key configuration, thoroughly test all related CRUD operations to ensure data consistency

Conclusion

Entity Framework Core's value generation mechanism relies on close coordination between data types and database features. String-type primary keys typically cannot achieve out-of-the-box auto-increment functionality due to database limitations. By changing primary key types to numeric, developers can fully leverage EF Core's automatic value generation features, simplifying data persistence logic and improving development efficiency. For special requirements necessitating string primary keys, explicit configuration is required to implement appropriate value generation strategies.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.