EF框架下如何正确使用JoinAwait实现异步关联查询 解决使用报错问题
首先你原来的代码报错有两个核心原因:
- 你将
_dbContext.Application转为IAsyncEnumerable后,调用的是同步Enumerable.Join方法,第二个参数传入的_dbContext.Users是IQueryable类型,类型不匹配,而且同步方法也无法适配异步序列的执行逻辑。 - 直接对
DbSet调用AsAsyncEnumerable()会触发客户端评估:EF会先把Application表的全量数据加载到内存,再在内存中执行关联逻辑,数据量稍大就会出现严重的性能问题。
两种适配方案
方案1:优先使用EF原生查询(推荐)
绝大多数EF关联查询场景不需要用到System.Linq.Async的API,直接使用IQueryable原生的Join方法,EF会自动把关联逻辑翻译成SQL在数据库层面执行,性能最优:
await _dbContext.Application .Join(_dbContext.Users, o => o.IdUser, i => i.Id, (o, i) => new { Id = o.Id }) .ToListAsync();
方案2:使用JoinAwait做异步内存关联
如果你确实有特殊场景需要在内存中做流式异步关联(比如需要关联两个无法在数据库层面拼接的异步序列),再使用JoinAwait,需要保证两个关联序列都是IAsyncEnumerable类型,且选择器返回ValueTask类型:
// 示例中IdUser、Id假设为Guid类型,替换为你实际的字段类型即可 await _dbContext.Application .AsAsyncEnumerable() .JoinAwait( _dbContext.Users.AsAsyncEnumerable(), o => new ValueTask<Guid>(o.IdUser), i => new ValueTask<Guid>(i.Id), (o, i) => new ValueTask<object>(new { Id = o.Id })) .ToListAsync();
注意事项
不要随意调用AsAsyncEnumerable(),该方法会中断EF的查询翻译链路,后续所有操作都将在客户端内存执行,只有你明确需要做客户端异步处理时再使用。
内容的提问来源于stack exchange,提问作者Pac-Man
相关产品推荐
相关产品推荐

