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

EF Core中FromSqlRaw方法在XUnit测试中报错的问题

问题原因与解决方法

问题本质

EF Core的内存数据库提供者(InMemoryDatabase)不支持原生SQL查询,包括FromSqlRaw和FromSqlInterpolated方法。你在测试中用内存库替代真实数据库,但该提供者无法处理原生SQL对应的查询表达式,所以抛出了FromSqlQueryRootExpression未被处理的错误。

可行解决方案

  • 改用SQLite内存模式做测试
    SQLite支持原生SQL,且可配置为内存模式,既能快速运行测试,又能兼容FromSqlRaw调用。配置方式如下:

    // 测试中配置DbContext
    var connection = new SqliteConnection("Data Source=:memory:");
    connection.Open(); // 必须保持连接打开,否则内存数据会丢失
    
    var options = new DbContextOptionsBuilder<YourDbContext>()
        .UseSqlite(connection)
        .Options;
    
    using var context = new YourDbContext(options);
    context.Database.EnsureCreated(); // 初始化表结构
    

    用这个context执行测试,就能正常调用FromSqlRaw了。

  • 抽象原生SQL逻辑,测试时替换实现
    把调用FromSqlRaw的业务逻辑抽成独立接口,比如:

    public interface IYourRepository
    {
        Task<YourEntity> GetEntityAsync(int id);
    }
    
    // 生产环境实现
    public class YourRepository : IYourRepository
    {
        private readonly YourDbContext _context;
    
        public YourRepository(YourDbContext context) => _context = context;
    
        public async Task<YourEntity> GetEntityAsync(int id)
        {
            return await _context.YourEntities
                .FromSqlRaw("SELECT * FROM YourEntities WHERE Id = {0}", id)
                .FirstOrDefaultAsync();
        }
    }
    

    测试时,用模拟实现或内存数据返回结果,完全绕过原生SQL:

    public class MockYourRepository : IYourRepository
    {
        public Task<YourEntity> GetEntityAsync(int id)
        {
            // 返回预设的测试数据
            return Task.FromResult(new YourEntity { Id = id, Name = "Test" });
        }
    }
    
  • 模拟DbSet跳过原生SQL执行
    如果不想重构代码,也可以用Moq等框架模拟DbSet,让FromSqlRaw调用直接返回预设数据:

    var mockSet = new Mock<DbSet<YourEntity>>();
    mockSet.Setup(m => m.FromSqlRaw(It.IsAny<string>(), It.IsAny<object[]>()))
            .Returns(mockSet.Object);
    mockSet.Setup(m => m.FirstOrDefaultAsync(It.IsAny<Expression<Func<YourEntity, bool>>>(), It.IsAny<CancellationToken>()))
            .ReturnsAsync(new YourEntity { Id = 1 });
    
    var mockContext = new Mock<YourDbContext>();
    mockContext.Setup(c => c.YourEntities).Returns(mockSet.Object);
    
    // 使用mockContext.Object执行测试
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 19:40:38