DbSet结合AsExpandable()执行异步查询时抛出InvalidOperationException异常
解决Expression<Func<>>异步查询因AsExpandable()导致的IDbAsyncEnumerable异常问题
问题核心是AsExpandable()返回的LINQKit包装查询未实现Entity Framework异步操作所需的IDbAsyncEnumerable接口,导致ToArrayAsync()等异步方法抛出异常。以下是几种可行的解决方案:
方案1:使用LINQKit官方异步扩展
LINQKit针对EF异步操作提供了专门的扩展支持,只需确保安装对应版本的LINQKit包(EF Core用LINQKit.Microsoft.EntityFrameworkCore,EF6用LINQKit.EntityFramework),即可直接适配异步操作:
代码示例
using LINQKit; Expression<Func<IDbUserRightsInfo, bool>> expression = u => u.MarketingType == eUserMarketingType.Internal; // 方式1:简化写法,直接通过AsExpandable()后的Where接收表达式 var result = await usersDbSet.AsExpandable() .Where(expression) .ToArrayAsync() .ConfigureAwait(false); // 方式2:保留原LINQ查询结构,通过ToAsyncEnumerable转换支持异步 var result = await (from u in usersDbSet.AsExpandable() where expression.Invoke(u) select u) .ToAsyncEnumerable() .ToArrayAsync() .ConfigureAwait(false);
方案2:手动合并表达式(不依赖LINQKit)
如果不想引入LINQKit依赖,可以手动将外部表达式合并到查询的Where子句中,避免使用AsExpandable():
代码示例
Expression<Func<IDbUserRightsInfo, bool>> expression = u => u.MarketingType == eUserMarketingType.Internal; // 创建查询参数并合并表达式 var parameter = Expression.Parameter(typeof(IDbUserRightsInfo), "u"); var mergedBody = Expression.Invoke(expression, parameter); var mergedExpression = Expression.Lambda<Func<IDbUserRightsInfo, bool>>(mergedBody, parameter); // 使用EF原生查询,天然支持异步 var result = await usersDbSet.Where(mergedExpression) .ToArrayAsync() .ConfigureAwait(false);
方案3:自定义IDbAsyncEnumerable包装类(进阶)
若需完全自定义扩展,可实现一个包装类,让AsExpandable()返回的IQueryable实现IDbAsyncEnumerable接口。不过此方法需要编写较多底层适配代码,推荐优先使用前两种方案。
内容的提问来源于stack exchange,提问作者Stephane Mathis
相关产品推荐
相关产品推荐

