EF Core 7 ExecuteDeleteAsync在内存数据库中执行报错问题
EF Core 7 ExecuteDeleteAsync()内存数据库测试失败问题
问题情况
EF Core 7新增的ExecuteDeleteAsync()功能在真实MsSql Server中可正常运行,但使用最新版Microsoft.EntityFrameworkCore.InMemory内存数据库编写测试用例时执行失败,推测是该特性的无追踪批量操作机制导致内存数据库不支持。
相关代码
删除方法
public async Task<int> DeleteWhere(Expression<Func<T, bool>> predicate) { var amount = await _dbSet.Where(predicate).ExecuteDeleteAsync(); return amount; }
数据库上下文创建代码
public DashboardDbContext CreateDashboardContext() { var dbName = $"xUnitTest{_instanceCount++}"; var builder = new DbContextOptionsBuilder<DashboardDbContext>(); builder.UseInMemoryDatabase(dbName); return new DashboardDbContext(builder.Options); }
抛出的异常信息(中文翻译)
{"LINQ表达式'DbSet()\r\n.Where(b => b.ModifiedTime < __dateToKeepData_0)\r\n .ExecuteDelete()'无法被转换。请将查询重写为可转换的形式,或者通过插入对'AsEnumerable'、'AsAsyncEnumerable'、'ToList'或'ToListAsync'的调用显式切换到客户端评估。"}
原因与解决方案
原因确认
你的推测完全正确:EF Core 7的ExecuteUpdate/ExecuteDelete属于无追踪批量操作,这类操作直接基于LINQ生成数据库层面的删除/更新语句,跳过EF的变更追踪系统。而InMemory内存数据库提供程序不支持这类批量操作的SQL翻译逻辑,仅能处理依赖变更追踪的常规CRUD操作。
解决方案
- 测试场景适配方案:改用客户端评估模拟批量删除(会先加载数据到内存再删除,和真实数据库批量操作行为有差异,仅适合测试):
public async Task<int> DeleteWhere(Expression<Func<T, bool>> predicate) { var entities = await _dbSet.Where(predicate).ToListAsync(); _dbSet.RemoveRange(entities); await _dbContext.SaveChangesAsync(); return entities.Count; } - 贴近真实环境测试方案:替换InMemory为SQLite内存数据库,SQLite支持EF Core批量操作的翻译逻辑,能更准确模拟真实数据库的行为。
内容的提问来源于stack exchange,提问作者KnApP993
相关产品推荐
相关产品推荐

