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

升级Entity Framework至6.0.12后Sqlite集成测试报错求助

EF从2.2.6升级至6.0.12后,内存Sqlite集成测试计算列函数报错问题解决

问题背景

将Entity Framework版本从2.2.6升级至6.0.12后,大量依赖内存Sqlite数据库的集成测试失败。问题与迁移中新增的数据库函数有关——该函数被用于DbContext的OnModelCreating()方法中定义计算列。

测试初始化执行以下代码:

_dbContext.Database.EnsureDeleted();
_dbContext.Database.EnsureCreated();

调用EnsureCreated()时抛出异常:

Microsoft.Data.Sqlite.SqliteException : SQLite Error 1: 'near "(": syntax error'

通过堆栈追踪定位到,异常触发于OnModelCreating()中的这段代码:

modelBuilder.Entity<MyObject>()
            .Property(p => p.LinkId)
            .HasComputedColumnSql("Schema.fn_link_id([Id])");

推测异常原因是EnsureCreated()不会执行迁移,导致数据库中不存在目标函数。

已尝试的无效方案

  • 用.Migrate()替代.EnsureCreated():由于Sqlite迁移存在列修改等限制,此方案失效;手动重写5年多的适配迁移成本过高,暂不考虑。
  • 使用.Migrate()并切换至本地SqlServer实例:本地测试可通过,但会增加CI/CD管道的额外开销与复杂度,不愿采用。
  • 在测试中直接创建函数绕过迁移需求:仍出现相同语法错误,代码示例:
var connection = new SqliteConnection("DataSource=:memory:");
connection.Open();

connection.CreateFunction("Schema.fn_link_id", (int Id) => Guid.NewGuid());

var options = new DbContextOptionsBuilder<MyDbContext>()
                .UseSqlite(connection)
                .Options;

可行解决方案

问题核心在于Sqlite不支持SQL Server风格的架构(Schema)前缀,且CreateFunction方法无法带架构名注册函数。需做两处修改:

1. 注册Sqlite函数时去掉架构前缀

Sqlite没有SQL Server的架构概念,注册函数时直接使用fn_link_id作为函数名:

var connection = new SqliteConnection("DataSource=:memory:");
connection.Open();

// 移除Schema前缀,仅注册函数名
connection.CreateFunction("fn_link_id", (int Id) => Guid.NewGuid().ToString());

var options = new DbContextOptionsBuilder<MyDbContext>()
                .UseSqlite(connection)
                .Options;

2. 动态调整计算列的SQL语句

在OnModelCreating()中,根据当前数据库类型动态修改计算列的函数调用语句,适配Sqlite与其他数据库(如SQL Server)的语法差异:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.Entity<MyObject>()
                .Property(p => p.LinkId)
                .HasComputedColumnSql(provider => 
                    provider == "Microsoft.EntityFrameworkCore.Sqlite" 
                        ? "fn_link_id([Id])" 
                        : "Schema.fn_link_id([Id])"
                );
}

这样修改后,内存Sqlite测试时会正确调用注册的函数,同时不影响生产环境中SQL Server的原有逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 19:25:47