EF6 无法将 Func lambda 识别为 Where 的过滤器

EF6 does not recognize Func lambda as filter for Where

我有以下实体:

[Table("Customer", Schema = "dbo")]
public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
}

[Table("Payment", Schema = "dbo")]
public class Payment
{
    public int PaymentId { get; set; }
    public int CustomerId { get; set; }
    public DateTime Period { get; set; }
    public int Price { get; set; }
    [ForeignKey("CustomerId")]
    public Customer Customer { get; set; }
}

现在我想通过 PeriodPrice 过滤 Payment table。每个谓词都必须在其自己的 Where 方法中。所以,我得到以下信息:

int price = 200;
var period = new DateTime(2020, 10, 3);

using var db = new TestContext();

// Option 1: anonymous lambda
var payments1 = db.Payments
                  .Where(p => p.Period < period)
                  .Where(p => p.Price <= price);

foreach (var payment in payments1)
{
    listBox.Items.Add(
        $"Payment: Payment Id={payment.PaymentId}, " +
        $"Customer Id`={payment.CustomerId}, " +
        $"Period={payment.Period.ToShortDateString()}, " +
        $"Price={payment.Price}");
}

EF6 生成正确的 SQL:

exec sp_executesql N'SELECT 
    [Extent1].[PaymentId] AS [PaymentId], 
    [Extent1].[CustomerId] AS [CustomerId], 
    [Extent1].[Period] AS [Period], 
    [Extent1].[Price] AS [Price]
    FROM [dbo].[Payment] AS [Extent1]
    WHERE ([Extent1].[Period] < @p__linq__0) AND ([Extent1].[Price] <= @p__linq__1)',
       N'@p__linq__0 datetime2(7),@p__linq__1 int',
       @p__linq__0='2020-10-03 00:00:00',
       @p__linq__1=200

但是,如果我在相同条件下使用 Func lambda:

// Option 2: Func<T, T> lambda
Func<Payment, bool> func = p => p.Period < period;
var payments2 = db.Payments.Where(func).Where(p => p.Price <= price);

我没有得到相同的 SQL,但得到这个:

SELECT 
    [Extent1].[PaymentId] AS [PaymentId], 
    [Extent1].[CustomerId] AS [CustomerId], 
    [Extent1].[Period] AS [Period], 
    [Extent1].[Price] AS [Price]
    FROM [dbo].[Payment] AS [Extent1]

据我了解,EF 已切换到客户端评估。我想知道,为什么会这样?我正在使用相同的 lambda 进行过滤!

您需要使用 Expression,而不仅仅是 Func,以便 EF 可以计算出属性的名称等

尝试:

Expression<Func<Payment, bool>> func = p => p.Period < period;