.NET Core EF Core单元测试:SQLite不支持APPLY操作致测试失败
问题原因
EF Core针对SQL Server和SQLite的查询翻译逻辑存在差异:当你在嵌套的Produits集合投影后使用Distinct()时,EF Core会为SQL Server生成依赖APPLY操作的SQL语句,但SQLite并不支持APPLY语法,因此单元测试抛出异常。移除Distinct()后,查询无需APPLY操作,SQLite可以正常解析执行。
解决方案
方案1:将去重逻辑移到客户端执行
先从数据库拉取完整数据到内存,再在客户端对集合做去重处理,避免EF Core生成SQLite不支持的语句:
// 提前Include关联的Produits,避免后续N+1查询 var commandes = await _context.Commandes .Where(c => c.Numero == numero) .Include(c => c.Produits) .ToListAsync(cancellationToken); var result = commandes.Select(command => new CommandeDto { Numero = command.Numero, Produits = command.Produits .Select(s => new ProduittDto { Id = s.Id, // 原代码中`s.s.Id`应为笔误,修正为`s.Id` Libelle = s.Name }) .Distinct() .ToList() }).ToList();
注意:如果ProduittDto没有重写Equals和GetHashCode,Distinct()可能无法按预期去重,需要为该DTO实现相等性判断逻辑,或者改用.NET 6+支持的DistinctBy:
.Produits .Select(s => new ProduittDto { Id = s.Id, Libelle = s.Name }) .DistinctBy(dto => new { dto.Id, dto.Libelle }) .ToList()
方案2:用GroupBy替代Distinct实现去重
通过GroupBy按去重字段分组,再从分组中取数据,EF Core可以将这种逻辑转换成SQLite支持的语句:
var result = await (from command in _context.Commandes where command.Numero == numero select new CommandeDto { Numero = command.Numero, Produits = command.Produits .GroupBy(s => new { s.Id, s.Name }) .Select(g => new ProduittDto { Id = g.Key.Id, Libelle = g.Key.Name }) .ToList() }).ToListAsync(cancellationToken);
方案3:统一单元测试与生产环境数据库
如果希望保持查询逻辑不变,可以改用支持APPLY操作的数据库做单元测试,比如SQL Server LocalDB或Docker化的SQL Server实例,这样查询在测试和生产环境的行为完全一致,避免数据库兼容性问题。
内容的提问来源于stack exchange,提问作者dna
相关产品推荐
相关产品推荐

