在 LINQ to entities 中使用 return IQueryable 的自定义方法

Using custom methods that return IQueryable in the LINQ to entities

我有两个方法 return 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 entities 中不受支持(抛出 NotSupportedException),除非我声明一个变量并在查询中使用它:

var bad = GetBadPeople()
var q = from x in GetGoodPeople()
        from y in bad
        select new { Good = x, Bad = y };

有没有一种方法可以直接在实体的 linq 中使用 IQueryable 方法?

简答 - 不可能可行。您的修复是解决问题的正确方法。

一旦 entity framework(以及 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)。请注意该查询如何 逐字 ,但 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))

请注意,这里没有方法调用 - 我们只是传入变量。

您可以使用不受约束的连接来近似笛卡尔积。它似乎不容易受到 NotSupportedException 的影响。我检查了后端,它呈现了一个 sql 语句。

var q = from x in GetGoodPeople()
        join y in GetBadPeople()
        on 1 equals 1
        select new { Good = x, Bad = y };