EF Core单元测试对接Sqlite内存数据库报AUTOINCREMENT错误如何排查
你现有的EF Core迁移是针对SQL Server生成的,使用的是T-SQL方言,默认Identity框架自带的AspNetRoleClaims、AspNetUserClaims等表的Id列被配置为int类型的自增主键。当你切换到Sqlite作为数据库提供器运行迁移时,EF Core会自动将自增配置翻译为Sqlite的AUTOINCREMENT关键字,但Sqlite语法明确要求:使用AUTOINCREMENT修饰的主键必须声明为INTEGER类型,和迁移中配置的int类型不兼容,因此触发报错。
你之前执行script-database -Idempotent生成的脚本是默认适配SQL Server的,自然不会包含AUTOINCREMENT相关内容,该关键字是EF Core运行时对接Sqlite提供器时动态生成的。
方案1:单元测试直接通过模型建表(最简便)
单元测试场景不需要验证迁移逻辑的前提下,不要调用Migrate()方法执行原有迁移,改为调用Database.EnsureCreated(),该方法会直接根据当前DbContext的模型结构,适配Sqlite语法生成兼容的表结构,不会触发原有迁移的SQL Server兼容配置。
示例代码:
// 单元测试DbContext初始化逻辑 var connection = new SqliteConnection("Filename=:memory:"); connection.Open(); var dbOptions = new DbContextOptionsBuilder<YourDbContext>() .UseSqlite(connection) .Options; var testDbContext = new YourDbContext(dbOptions); // 替代testDbContext.Database.Migrate() testDbContext.Database.EnsureCreated();
方案2:配置多提供器兼容规则
如果需要在测试中执行迁移验证迁移正确性,可以在模型配置中针对Sqlite做专属适配:
在你的DbContext的OnModelCreating方法中,判断当前使用的数据库提供器,修改Identity表的主键字段类型适配Sqlite要求:
protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // 仅针对Sqlite提供器修改配置 if (Database.ProviderName == "Microsoft.EntityFrameworkCore.Sqlite") { // 适配AspNetRoleClaims表主键 modelBuilder.Entity<AspNetRoleClaim>() .Property(c => c.Id) .HasColumnType("INTEGER"); // 其他带自增主键的Identity表按相同逻辑适配即可 modelBuilder.Entity<AspNetUserClaim>() .Property(c => c.Id) .HasColumnType("INTEGER"); } }
配置完成后重新生成迁移即可同时兼容SQL Server和Sqlite两种提供器。
方案3:生成Sqlite专属迁移
你也可以单独为Sqlite生成一套独立的迁移文件,运行单元测试时指定使用Sqlite专属的迁移集即可,完全避免多提供器的配置冲突。
内容的提问来源于stack exchange,提问作者Greg B

