我有以下实体:
[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
表。每个谓词都必须在自己的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进行过滤!
您需要使用表达式,而不仅仅是函数这样EF才能计算出属性等的名称。
尝试:
Expression<Func<Payment, bool>> func = p => p.Period < period;