Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions entity-framework/core/providers/sqlite/value-generation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
title: SQLite Database Provider - Value Generation - EF Core
description: Value Generation Patterns Specific to the SQLite Entity Framework Core Database Provider
author: AndriySvyryd
ms.date: 09/26/2025
uid: core/providers/sqlite/value-generation
---
# SQLite Value Generation

This page details value generation configuration and patterns that are specific to the SQLite provider. It's recommended to first read [the general page on value generation](xref:core/modeling/generated-properties).

## AUTOINCREMENT columns

By convention, numeric primary key columns that are configured to have their values generated on add are set up with SQLite's AUTOINCREMENT feature. Starting with EF Core 10, SQLite AUTOINCREMENT is a first-class feature with full support through conventions and the Fluent API.

### Configuring AUTOINCREMENT

By convention, integer primary keys are automatically configured with AUTOINCREMENT when they are not composite and don't have a foreign key on them. However, you may need to explicitly configure a property to use SQLite AUTOINCREMENT when the property has a value conversion from a non-integer type, or when overriding conventions:

[!code-csharp[Main](../../../../samples/core/Sqlite/ValueGeneration/SqliteAutoincrementWithValueConverter.cs?name=SqliteAutoincrementWithValueConverter&highlight=6)]

## Disabling AUTOINCREMENT for default SQLite value generation

In some cases, you may want to disable AUTOINCREMENT and use SQLite's default value generation behavior instead. You can do this using the Metadata API:

[!code-csharp[Main](../../../../samples/core/Sqlite/ValueGeneration/SqliteValueGenerationStrategyNone.cs?name=SqliteValueGenerationStrategyNone&highlight=5)]

Starting with EF Core 10, you can also use the strongly-typed Metadata API:

```csharp
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Post>()
.Property(p => p.Id)
.Metadata.SetValueGenerationStrategy(SqliteValueGenerationStrategy.None);
}
```

Alternatively, you can disable value generation entirely:

```csharp
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.Property(b => b.Id)
.ValueGeneratedNever();
}
```

This means that it's up to the application to supply a value for the property before saving to the database. Note that this still won't disable the default value generation server-side, so non-EF usages could still get a generated value. To completely disable value generation the user can change the column type from `INTEGER` to `INT`.

## Migration behavior

When EF Core generates migrations for SQLite AUTOINCREMENT columns, the generated migration will include the `Sqlite:Autoincrement` annotation:

```csharp
migrationBuilder.CreateTable(
name: "Blogs",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Title = table.Column<string>(type: "TEXT", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Blogs", x => x.Id);
});
```

This ensures that the AUTOINCREMENT feature is properly applied when the migration is executed against the SQLite database.
10 changes: 10 additions & 0 deletions entity-framework/core/what-is-new/ef-core-10.0/whatsnew.md
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,16 @@ await context.Blogs.ExecuteUpdateAsync(s =>

Thanks to [@aradalvand](https://github.com/aradalvand) for proposing and pushing for this change (in [#32018](https://github.com/dotnet/efcore/issues/32018)).

<a name="sqlite"></a>

## SQLite

### Improved AUTOINCREMENT support

SQLite AUTOINCREMENT is now a first-class feature with full support through conventions and the Fluent API. Previously, properties with value converters couldn't configure AUTOINCREMENT and would cause false pending model change warnings.

For more information, see [SQLite Value Generation](xref:core/providers/sqlite/value-generation).

<a name="other-improvements"></a>

## Other improvements
Expand Down
2 changes: 2 additions & 0 deletions entity-framework/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,8 @@
href: core/providers/sqlite/limitations.md
- name: Function mappings
href: core/providers/sqlite/functions.md
- name: Value generation
href: core/providers/sqlite/value-generation.md
- name: Spatial data
displayName: GIS
href: core/providers/sqlite/spatial.md
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using Microsoft.EntityFrameworkCore;

namespace EFCore.Sqlite.ValueGeneration;

public readonly struct BlogId
{
public BlogId(int value) => Value = value;
public int Value { get; }

public static implicit operator int(BlogId id) => id.Value;
public static implicit operator BlogId(int value) => new(value);
}

public class SqliteAutoincrementWithValueConverterContext : DbContext
{
public DbSet<BlogPost> Blogs { get; set; }

#region SqliteAutoincrementWithValueConverter
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<BlogPost>()
.Property(b => b.Id)
.HasConversion<int>()
.UseAutoincrement();
}
#endregion

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseSqlite("Data Source=sample.db");
}

public class BlogPost
{
public BlogId Id { get; set; }
public string Title { get; set; }
}
14 changes: 14 additions & 0 deletions samples/core/Sqlite/ValueGeneration/SqliteValueGeneration.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>disable</Nullable>
<OutputType>Library</OutputType>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.0-rc.1.25451.107" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Sqlite.Metadata;

namespace EFCore.Sqlite.ValueGeneration;

public class SqliteValueGenerationStrategyNoneContext : DbContext
{
public DbSet<Post> Posts { get; set; }

#region SqliteValueGenerationStrategyNone
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Post>()
.Property(p => p.Id)
.Metadata.SetValueGenerationStrategy(SqliteValueGenerationStrategy.None);
}
#endregion

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseSqlite("Data Source=sample.db");
}

public class Post
{
public int Id { get; set; }
public string Content { get; set; }
}
5 changes: 5 additions & 0 deletions samples/global.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"sdk": {
"version": "10.0.100-rc.1.25451.107"
}
}
Loading