You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF Core反向生成SQLite自增主键类时的ValueGeneratedNever问题

Fixing EF Core SQLite Scaffold's Incorrect Auto-Increment ID Configuration

I get exactly what you're dealing with—EF Core's scaffolding tool misconfigures SQLite's AUTOINCREMENT primary keys as ValueGeneratedNever(), which causes duplicate ID errors when adding new records. Since you want to stick with your database-first workflow and can't switch to the old Entity Framework on UWP, here are several solid solutions:

1. Customize the EF Core Scaffolding Template

This is a one-time fix that ensures every scaffold run generates the correct ID configuration. Here's how to do it:

  • First, list the available scaffolding templates to find the right one:
    dotnet ef dbcontext scaffold --list-templates
    
  • Export the default templates to a local folder in your project:
    dotnet ef dbcontext scaffold --export-templates
    
  • Open the EntityType.cs.tmpl file (the template for generating entity configurations) and locate the section that handles primary key generation strategies. For SQLite columns marked as INTEGER PRIMARY KEY AUTOINCREMENT, modify the logic to output .ValueGeneratedOnAdd() instead of .ValueGeneratedNever().
  • Next time you run the scaffold command, point it to your custom template folder:
    Scaffold-DbContext "DataSource=MyApp.sqlite;" Microsoft.EntityFrameworkCore.Sqlite -OutputDir Models -force -TemplatePath ./Templates
    
    (Replace ./Templates with the path to your custom template directory.)

2. Use Partial Classes + IEntityTypeConfiguration

Since the scaffolded model and context classes are partial, you can add your own configuration that overrides the scaffolded settings—this way, your fixes won't get wiped when you regenerate the code.

  • Create a new configuration class in your Models folder:
    using Microsoft.EntityFrameworkCore;
    using Microsoft.EntityFrameworkCore.Metadata.Builders;
    
    namespace YourAppNamespace.Models
    {
        public class LastSyncTimeConfiguration : IEntityTypeConfiguration<LastSyncTime>
        {
            public void Configure(EntityTypeBuilder<LastSyncTime> builder)
            {
                // Override the ID generation strategy
                builder.Property(e => e.Id)
                    .HasColumnName("ID")
                    .ValueGeneratedOnAdd();
            }
        }
    }
    
  • Then, create a partial MyAppContext class (separate from the scaffolded one) to apply this configuration:
    using Microsoft.EntityFrameworkCore;
    
    namespace YourAppNamespace.Models
    {
        public partial class MyAppContext : DbContext
        {
            protected override void OnModelCreating(ModelBuilder modelBuilder)
            {
                // Apply our custom configuration first
                modelBuilder.ApplyConfiguration(new LastSyncTimeConfiguration());
                
                // Call the scaffolded OnModelCreating logic
                base.OnModelCreating(modelBuilder);
            }
        }
    }
    
    Now, even when you regenerate the context, your partial class won't be overwritten, and your correct ID configuration will take precedence.

3. Switch to Code-First Workflow (UWP-Friendly)

While you prefer database-first, UWP fully supports EF Core's code-first approach. This lets you define your model's ID strategy directly in code, eliminating scaffolding errors entirely.
Here's what your model would look like:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace YourAppNamespace.Models
{
    public class LastSyncTime
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int ID { get; set; }
        
        [Required]
        public string SyncTime { get; set; }
        
        [Required]
        public string TableUpdated { get; set; }
    }
}

You'd then use Add-Migration and Update-Database to create and update your SQLite database—this ensures the auto-increment behavior is configured correctly from the start.

4. Manual Fix (Quick but Not Ideal)

If you need a temporary workaround, you can manually replace .ValueGeneratedNever() with .ValueGeneratedOnAdd() every time you scaffold. But this is repetitive and error-prone, so it's only good for quick fixes, not long-term use.


For your use case, either the custom scaffold template or partial class configuration is the best fit—they let you keep your database-first workflow without manual edits. Code-first is also a great option if you're open to adjusting your workflow for more control.

内容的提问来源于stack exchange,提问作者Dan Is Fiddling By Firelight

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:41:09