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

如何在SQLite中为非主键长整型字段实现自增

解决SQLite中非主键字段自增的问题

SQLite和SQL Server的自增机制存在差异——SQL Server允许非主键字段设为标识列自动生成值,但SQLite仅支持主键字段关联AUTOINCREMENT(或隐式rowid自增),非主键字段无法通过EF Core的UseIdentityColumn+ValueGeneratedOnAdd自动生成值,这就是触发NOT NULL约束错误的核心原因。

以下是几种可行的解决办法:

方法1:用SQLite触发器实现自增

给目标表创建触发器,插入时自动计算并赋值给非主键字段:

CREATE TRIGGER Trigger_Increment_FieldName
AFTER INSERT ON TableName
FOR EACH ROW
WHEN NEW.FieldName IS NULL
BEGIN
  UPDATE TableName 
  SET FieldName = (SELECT COALESCE(MAX(FieldName), 0) + 1 FROM TableName)
  WHERE rowid = NEW.rowid;
END;

对应的EF Core配置去掉UseIdentityColumn,保留ValueGeneratedOnAdd即可:

builder.Property(b => b.FieldName)
    .ValueGeneratedOnAdd();

插入数据时无需手动给FieldName赋值,触发器会自动处理。

方法2:EF Core层面手动生成自增值

如果不想依赖数据库触发器,可以在DbContext中重写保存方法,在数据插入前手动计算并赋值:

public override int SaveChanges()
{
    var addedEntities = ChangeTracker.Entries<YourEntity>()
        .Where(e => e.State == EntityState.Added && e.Entity.FieldName == 0);

    foreach (var entity in addedEntities)
    {
        // 获取当前最大的FieldName值,无数据则从0开始加1
        var maxValue = Set<YourEntity>().Max(e => (int?)e.FieldName) ?? 0;
        entity.Entity.FieldName = maxValue + 1;
    }

    return base.SaveChanges();
}

⚠️ 注意:这种方式在多并发插入场景下可能出现重复值,适合测试或单用户场景,生产环境需额外加锁处理。

方法3:改用Guid类型(业务允许的话)

如果不需要连续数字的自增ID,可以把字段类型换成Guid,让数据库自动生成唯一值:

// 针对不同数据库配置默认值
if (Database.ProviderName == "Microsoft.EntityFrameworkCore.Sqlite")
{
    builder.Property(b => b.FieldName)
        .HasDefaultValueSql("uuid()")
        .ValueGeneratedOnAdd();
}
else
{
    builder.Property(b => b.FieldName)
        .HasDefaultValueSql("NEWID()")
        .ValueGeneratedOnAdd();
}

这种方式无需关心自增逻辑,生成的Guid天然唯一,适配多数业务场景。

内容的提问来源于stack exchange,提问作者walruz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 23:26:03