EF Core使用List替代DbSet定义ToInMemoryQuery报错如何解决
解决EF Core ToInMemoryQuery无法使用List作为数据源的问题
问题复现
在EF Core中,常规为无键实体配置内存查询的写法基于DbSet作为数据源,示例如下:
modelBuilder.Entity<UrlResource>() .ToInMemoryQuery(() => context.Blogs.Select(b => new UrlResource { Url = b.Url }));
单元测试场景下,若尝试直接使用List作为查询源,两种常见写法都会抛出异常:
- 第一种写法:先将List转为IQueryable再传入
抛出异常:var urlResources = new List<UrlResource>() { ... }.AsQueryable(); modelBuilder.Entity<UrlResource>() .ToInMemoryQuery(() => urlResources);The LINQ expression could not be translated. - 第二种写法:在Lambda内调用AsQueryable
抛出参数类型不匹配的ArgumentException:var urlResources = new List<UrlResource>() { ... }; modelBuilder.Entity<UrlResource>() .ToInMemoryQuery(() => urlResources.AsQueryable());System.ArgumentException : Expression of type 'System.Collections.Generic.List
1[UrlResource]' cannot be used for parameter of type 'System.Linq.IQueryable1[UrlResource]' of method 'System.Linq.IQueryable1[UrlResource] Where[UrlResource](System.Linq.IQueryable1[UrlResource], System.Linq.Expressions.Expression1[System.Func2[UrlResource,System.Boolean]])' (Parameter 'arg0')
报错原因
ToInMemoryQuery 传入的Lambda表达式会被EF Core查询翻译器解析,直接捕获外部List/IQueryable变量时,翻译器会将其识别为闭包引用的未知常量,无法识别为可遍历的内存查询源,最终在翻译或执行阶段抛出异常。
可行解决方法
根据使用的EF Core版本和场景,可选择以下方案:
- 直接在Lambda内初始化集合(兼容所有EF Core版本)
不要捕获外部变量,直接在查询表达式内初始化List并转为IQueryable,EF Core可以正常解析这类固定值的集合初始化逻辑:modelBuilder.Entity<UrlResource>() .ToInMemoryQuery(() => new List<UrlResource> { // 填充测试数据 new UrlResource { Url = "https://example.com" } }.AsQueryable()); - 用EF.Constant包装外部集合(EF Core 5.0+可用)
如果需要动态传入外部定义的List,使用EF.Constant将集合标记为EF Core可识别的常量节点,避免翻译错误:var urlResources = new List<UrlResource>() { // 提前初始化好测试数据 }; modelBuilder.Entity<UrlResource>() .ToInMemoryQuery(() => EF.Constant(urlResources).AsQueryable()); - 单元测试场景优先用内存数据库填充数据
如果是单元测试场景,更推荐直接使用EF Core官方的InMemory内存数据库,在测试执行时直接往对应DbSet添加测试数据、调用SaveChanges即可,不需要额外配置ToInMemoryQuery,模拟的运行逻辑和生产环境更接近。
内容的提问来源于stack exchange,提问作者arkord
相关产品推荐
相关产品推荐

