表达式树查询语句中ArgumentException异常的问题排查
EF Core拆分查询表达式引发的类型不匹配问题
尝试将冗长的EF Core查询拆分为更易读的形式时,调用SingleOrDefaultAsync触发了ArgumentException,提示Func(Of Challenge, Boolean)类型无法匹配Expression(Of Func(Of Challenge, Boolean))参数。直接内嵌Lambda表达式不会报错,但拆分后声明的oQuery类型看起来和Session.Challenges.Any的参数一致,想知道问题原因。
原冗长代码
Dim oSession As Session oSession = Await Me.DbContext.Sessions.SingleOrDefaultAsync(Function(Session) Session.Challenges.Any(Function(Challenge) Not Challenge.Responses.Any))
拆分后报错代码
Dim oExpression As Expression(Of Func(Of Session, Boolean)) Dim oSession As Session Dim oQuery As Func(Of Challenge, Boolean) oQuery = Function(Challenge) Not Challenge.Responses.Any oExpression = Function(Session) Session.Challenges.Any(oQuery) oSession = Await Me.DbContext.Sessions.SingleOrDefaultAsync(oExpression)
异常信息
表达式类型“Func(Of Challenge, Boolean)”不能用于方法“Boolean Any(Of Challenge)(IQueryable(Of Challenge), Expression(Of Func(Of Challenge,Boolean)))”的参数“arg1”(参数名称“arg1”)
问题原因
EF Core针对数据库查询的IQueryable.Any()方法,要求传入的参数是表达式树(Expression(Of Func(Of T, Boolean))),而不是普通的委托(Func(Of T, Boolean))。
- 直接内嵌Lambda时,编译器会自动推断并将Lambda转换为
Expression类型,匹配IQueryable.Any()的重载; - 但拆分后如果把
oQuery声明为Func(Of Challenge, Boolean),它就只是一个内存中执行的委托,无法被EF Core解析为SQL查询逻辑,因此调用Session.Challenges.Any(oQuery)时,会因类型不匹配报错。
修正方案
将oQuery的类型改为Expression(Of Func(Of Challenge, Boolean))即可:
Dim oExpression As Expression(Of Func(Of Session, Boolean)) Dim oSession As Session Dim oQuery As Expression(Of Func(Of Challenge, Boolean)) oQuery = Function(Challenge) Not Challenge.Responses.Any oExpression = Function(Session) Session.Challenges.Any(oQuery) oSession = Await Me.DbContext.Sessions.SingleOrDefaultAsync(oExpression)
内容的提问来源于stack exchange,提问作者InteXX
相关产品推荐
相关产品推荐

