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; }
}
现在我想通过 Period
和 Price
过滤 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;
我有以下实体:
[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; }
}
现在我想通过 Period
和 Price
过滤 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;