我有两种返回IQueryable的方法:
IQueryable<Person> GetGoodPeople();
和
IQueryable<Person> GetBadPeople();
我需要写这个查询:
var q = from x in GetGoodPeople()
from y in GetBadPeople()
select new { Good = x, Bad = y };
linq to实体不支持上面的代码(抛出NotSupportedException
),除了我声明一个变量并在查询中使用它:
var bad = GetBadPeople()
var q = from x in GetGoodPeople()
from y in bad
select new { Good = x, Bad = y };
有没有办法可以直接在linq中使用IQueryable方法?
答案 0 :(得分:3)
简短回答 - 这不可能可行。您的修复是解决问题的正确方法。
一旦实体框架(以及LINQ2Sql)开始解析表达式树,就太晚了。对GetBadPeople()
的调用实际上是懒惰地执行,因此,尝试将其转换为SQL 本身。
这是它的样子:
Table(Person).Take(1).SelectMany(x => value(UserQuery).GetBadPeople(), (x, y) => new <>f__AnonymousType0`2(Good = x, Bad = y))
在这里,我写了GetGoodPeople()
只是简单地返回People.Take(1)
。请注意该查询是如何 verbatim ,但GetBadPeople()
包含函数调用。
在表达式之外评估GetBadPeople()
的解决方法是正确的解决方案。这会导致表达式树调用Expression.Constant(bad)
,而不是尝试调用GetBadPeople()
。
这使查询看起来像这样:
Table(Person).Take(1).SelectMany(x => value(UserQuery+<>c__DisplayClass1_0).bad, (x, y) => new <>f__AnonymousType0`2(Good = x, Bad = y))
注意这里没有方法调用 - 我们只是传入变量。
答案 1 :(得分:0)
您可以使用无约束连接来近似笛卡尔积。它似乎不容易受到NotSupportedException的影响。我检查了后端,它呈现了一个单独的sql语句。
var q = from x in GetGoodPeople()
join y in GetBadPeople()
on 1 equals 1
select new { Good = x, Bad = y };