我正在尝试修复一些性能不佳的Linq查询,但我遇到了Linq语法问题。我比SQL更擅长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< Func< TblBrandSpend,bool>>
它适用于使用连接的版本:
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;
有什么想法吗?
答案 0 :(得分:3)
我可以在类似的查询表达式中重现这一点。异常的堆栈跟踪如下所示:
at 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(IEnumerable
1集合)
在System.Linq.Enumerable.ToList [TSource](IEnumerable`1 source)
因此,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;
顺便说一句,它适用于实体框架。