【问题标题】:Linq - Unsupported overload used for query operator 'Where' using a PredicateLinq - 使用谓词的查询运算符“Where”使用不受支持的重载
【发布时间】:2015-01-15 17:57:07
【问题描述】:

我正在尝试修复一些性能不佳的 Linq 查询,但我遇到了 Linq 语法问题。我比 Linq 更擅长 SQL。

当前的工作版本只使用联接,但这效率低下,因为它返回多行,然后是 DISTINCTed。我想将连接转换为 EXISTS 子句。当我在 Where 子句中添加谓词时,它几乎可以工作,但会窒息。代码编译,但我得到上述错误。在 SO 上存在类似错误消息的问题,但它们似乎都在处理略有不同的场景。

此代码有效:

query = from contact in query
        where Context.TblJobToBrandLink.Join(Context.TblBrandSpends
                                                    //.Where(spendExpression)
                                                    .Where(x => x.IntBrandiD != 0), 
                                             x => x.IntBrandId, 
                                             y => y.IntBrandiD, 
                                             (x, y) => x
                                            ).Any(jobToBrand => jobToBrand.IntJobId == contact.IntJobId)
        select contact;

生成的 SQL 完全符合我的预期。

如果我用 .Where(spendExpression) 取消注释该行,我会收到不受支持的重载错误。

spendExpression 的类型为 Linq.Expressions.Expression>

它在使用连接的版本中工作:

query = from contact in query
        join jobToBrand in Context.TblJobToBrandLink on contact.IntJobId equals jobToBrand.IntJobId
        join brandSpend in Context.TblBrandSpends.Where(spendExpression) on jobToBrand.IntBrandId equals brandSpend.IntBrandiD
        where brandSpend.IntBrandiD != 0
        select contact;

有什么想法吗?

【问题讨论】:

  • 你不能把两个子句都放在一个 Where 和 && them 中吗?
  • 我确实尝试过 - 不幸的是 lambda 类型表达式和谓词类型表达式不能以这种方式使用。
  • 这似乎是谓词类型的问题 - 如果我整理数据库,我可以删除另一个 Where 子句,因为无论如何都不应该有任何 ID 为 0 的品牌,但我们有打算稍后在项目中这样做,因为速度是一个更紧迫的问题。

标签: c# linq linq-to-sql


【解决方案1】:

我可以在类似的查询表达式中重现这一点。异常的堆栈跟踪如下所示:

在 System.Data.Linq.SqlClient.QueryConverter.VisitSequenceOperatorCall(MethodCallExpression mc)
在 System.Data.Linq.SqlClient.QueryConverter.VisitMethodCall(MethodCallExpression mc)
在 System.Data.Linq.SqlClient.QueryConverter.VisitInner(表达式节点)
在 System.Data.Linq.SqlClient.QueryConverter.VisitWhere(表达式序列,LambdaExpression 谓词)
...
在 System.Collections.Generic.List1..ctor(IEnumerable1 集合)
在 System.Linq.Enumerable.ToList[TSource](IEnumerable`1 源)

因此,LINQ-to-SQL 表达式访问者遇到了一些意想不到的复杂性。这意味着这只是一个错误,您必须解决它。

有效的(在我的情况下)是直接使用表达式:

query = from contact in query
        where Context.TblJobToBrandLink
                     .Join(Context.TblBrandSpends
                     .Where(x => ...) // spendExpression's Expression here
                     ...

或在查询之外参与Context.TblBrandSpends.Where(spendExpression).Where(x => x.IntBrandiD != 0)

var brandSpends = Context.TblBrandSpends
                         .Where(spendExpression)
                         .Where(x => x.IntBrandiD != 0);

query = from contact in query
        where Context.TblJobToBrandLink
                     .Join(brandSpends,
                         x => x.IntBrandId, 
                         y => y.IntBrandiD, 
                         (x, y) => x)
                     .Any(jobToBrand => jobToBrand.IntJobId == contact.IntJobId)
        select contact;

顺便说一句,它在实体框架中工作。

【讨论】:

  • 我使用了你给出的底部示例,它运行良好!非常感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多