Skip to content

Commit 00a9555

Browse files
CopilotAndriySvyryd
andcommitted
Add SQLite value generation documentation and samples
Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
1 parent 0811647 commit 00a9555

File tree

7 files changed

+200
-0
lines changed

7 files changed

+200
-0
lines changed

entity-framework/core/providers/sqlite/index.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,7 @@ Install-Package Microsoft.EntityFrameworkCore.Sqlite
3434
## Limitations
3535

3636
See [SQLite Limitations](xref:core/providers/sqlite/limitations) for some important limitations of the SQLite provider.
37+
38+
## Additional Resources
39+
40+
* [SQLite Value Generation](xref:core/providers/sqlite/value-generation) - Information about SQLite AUTOINCREMENT and value generation patterns.
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
---
2+
title: SQLite Database Provider - Value Generation - EF Core
3+
description: Value Generation Patterns Specific to the SQLite Entity Framework Core Database Provider
4+
author: AndriySvyryd
5+
ms.date: 09/26/2025
6+
uid: core/providers/sqlite/value-generation
7+
---
8+
# SQLite Value Generation
9+
10+
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).
11+
12+
## AUTOINCREMENT columns
13+
14+
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.
15+
16+
### Configuring AUTOINCREMENT
17+
18+
Starting with EF Core 10, you can explicitly configure a property to use SQLite AUTOINCREMENT using the new Fluent API:
19+
20+
```csharp
21+
protected override void OnModelCreating(ModelBuilder modelBuilder)
22+
{
23+
modelBuilder.Entity<Blog>()
24+
.Property(b => b.Id)
25+
.UseAutoincrement();
26+
}
27+
```
28+
29+
You can also configure AUTOINCREMENT using the annotation API:
30+
31+
[!code-csharp[Main](../../../../samples/core/Sqlite/ValueGeneration/SqliteAutoincrement.cs?name=SqliteAutoincrement&highlight=5)]
32+
33+
This is equivalent to using the more general value generation API:
34+
35+
```csharp
36+
protected override void OnModelCreating(ModelBuilder modelBuilder)
37+
{
38+
modelBuilder.Entity<Blog>()
39+
.Property(b => b.Id)
40+
.ValueGeneratedOnAdd();
41+
}
42+
```
43+
44+
By convention, integer primary keys are automatically configured with AUTOINCREMENT when they don't have an explicitly assigned value.
45+
46+
### Working with value converters
47+
48+
Starting with EF Core 10, SQLite AUTOINCREMENT works properly with value converters. Previously, properties with value converters weren't able to configure AUTOINCREMENT. For example:
49+
50+
[!code-csharp[Main](../../../../samples/core/Sqlite/ValueGeneration/SqliteAutoincrementWithValueConverter.cs?name=SqliteAutoincrementWithValueConverter&highlight=6)]
51+
52+
In earlier versions of EF Core, this scenario would not work correctly and migrations would keep regenerating the same AlterColumn operation even without model changes.
53+
54+
## Disabling AUTOINCREMENT for default SQLite value generation
55+
56+
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:
57+
58+
[!code-csharp[Main](../../../../samples/core/Sqlite/ValueGeneration/SqliteValueGenerationStrategyNone.cs?name=SqliteValueGenerationStrategyNone&highlight=5)]
59+
60+
Alternatively, you can disable value generation entirely:
61+
62+
```csharp
63+
protected override void OnModelCreating(ModelBuilder modelBuilder)
64+
{
65+
modelBuilder.Entity<Blog>()
66+
.Property(b => b.Id)
67+
.ValueGeneratedNever();
68+
}
69+
```
70+
71+
This means that it's up to the application to supply a value for the property before saving to the database.
72+
73+
## Migration behavior
74+
75+
When EF Core generates migrations for SQLite AUTOINCREMENT columns, the generated migration will include the `Sqlite:Autoincrement` annotation:
76+
77+
```csharp
78+
migrationBuilder.CreateTable(
79+
name: "Blogs",
80+
columns: table => new
81+
{
82+
Id = table.Column<int>(type: "INTEGER", nullable: false)
83+
.Annotation("Sqlite:Autoincrement", true),
84+
Title = table.Column<string>(type: "TEXT", nullable: true)
85+
},
86+
constraints: table =>
87+
{
88+
table.PrimaryKey("PK_Blogs", x => x.Id);
89+
});
90+
```
91+
92+
This ensures that the AUTOINCREMENT feature is properly applied when the migration is executed against the SQLite database.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// This file is for documentation samples only.
2+
// The actual implementation code is in the individual sample files.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using Microsoft.EntityFrameworkCore;
2+
3+
namespace EFCore.Sqlite.ValueGeneration;
4+
5+
internal class SqliteAutoincrementContext : DbContext
6+
{
7+
public DbSet<Blog> Blogs { get; set; }
8+
9+
#region SqliteAutoincrement
10+
protected override void OnModelCreating(ModelBuilder modelBuilder)
11+
{
12+
modelBuilder.Entity<Blog>()
13+
.Property(b => b.Id)
14+
.HasAnnotation("Sqlite:Autoincrement", true);
15+
}
16+
#endregion
17+
18+
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
19+
=> optionsBuilder.UseSqlite("Data Source=sample.db");
20+
}
21+
22+
public class Blog
23+
{
24+
public int Id { get; set; }
25+
public string Title { get; set; }
26+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using Microsoft.EntityFrameworkCore;
2+
3+
namespace EFCore.Sqlite.ValueGeneration;
4+
5+
public readonly struct BlogId
6+
{
7+
public BlogId(int value) => Value = value;
8+
public int Value { get; }
9+
10+
public static implicit operator int(BlogId id) => id.Value;
11+
public static implicit operator BlogId(int value) => new(value);
12+
}
13+
14+
internal class SqliteAutoincrementWithValueConverterContext : DbContext
15+
{
16+
public DbSet<BlogPost> Blogs { get; set; }
17+
18+
#region SqliteAutoincrementWithValueConverter
19+
protected override void OnModelCreating(ModelBuilder modelBuilder)
20+
{
21+
modelBuilder.Entity<BlogPost>()
22+
.Property(b => b.Id)
23+
.HasConversion<int>()
24+
.HasAnnotation("Sqlite:Autoincrement", true);
25+
}
26+
#endregion
27+
28+
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
29+
=> optionsBuilder.UseSqlite("Data Source=sample.db");
30+
}
31+
32+
public class BlogPost
33+
{
34+
public BlogId Id { get; set; }
35+
public string Title { get; set; }
36+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>disable</Nullable>
7+
<OutputType>Library</OutputType>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.0" />
12+
</ItemGroup>
13+
14+
</Project>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using Microsoft.EntityFrameworkCore;
2+
3+
namespace EFCore.Sqlite.ValueGeneration;
4+
5+
internal class SqliteValueGenerationStrategyNoneContext : DbContext
6+
{
7+
public DbSet<Post> Posts { get; set; }
8+
9+
#region SqliteValueGenerationStrategyNone
10+
protected override void OnModelCreating(ModelBuilder modelBuilder)
11+
{
12+
modelBuilder.Entity<Post>()
13+
.Property(p => p.Id)
14+
.HasAnnotation("Sqlite:ValueGenerationStrategy", "None");
15+
}
16+
#endregion
17+
18+
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
19+
=> optionsBuilder.UseSqlite("Data Source=sample.db");
20+
}
21+
22+
public class Post
23+
{
24+
public int Id { get; set; }
25+
public string Content { get; set; }
26+
}

0 commit comments

Comments
 (0)