在 LINQ 中传入实体的 属性 in Entity Framework
Passing in an entity's property in Entity Framework in LINQ
我不确定我的问题是否有意义,但我们开始吧。我有一个非常复杂的查询,它从依赖运行时变量的 EF 转换为 SQL。
示例:假设我有一个实体对象。
public class Foobar
{
public int ID { get; set; }
public double AmountOne { get; set; }
public double AmountTwo { get; set; }
}
并且我想根据运行时间属性 查询Foobar 的金额字段之一。现在我知道有两种方法可以做到这一点。
方式#1:在代码中
public bool ShouldGetFirstAmount {get; set;}
public double GetFirstAmount()
{
if (ShouldGetFirstAmount)
{
return repository.Foobars.Select(c => c.AmountOne).First();
} else {
return repository.Foobars.Select(c => c.AmountTwo).First();
}
}
优点:sql 查询更小,开销更低
缺点:巨大的代码块/重复
方式 #2:直接在查询中,EF 可以对其进行转换。
public bool ShouldGetFirstAmount {get; set;}
public double GetFirstAmount()
{
return repository.Foobars.Select(c => ShouldGetFirstAmount ? c.AmountOne : c.AmountTwo).First();
}
优点:更小的代码块。
缺点:查询性能因实际查询中的表达式而受到影响
所以我正在寻找第三种方法,让我能够两全其美。我希望能够传入应该计算的实际对象 属性。我只是不确定应该如何完成,或者是否可以完成。
有点像这样的东西。我知道这段代码不起作用,但我想你们明白我想要的想法。
public Expression<double> FirstAmountProperty {get; set;}
public double GetFirstAmount()
{
return repository.Foobars.Select(FirstAmountProperty).First();
}
你很接近。如果 repository.Foobars
是 IQueryable<Foobar>
类型,则表达式需要是 Expression<Func<Foobar, double>>
类型。
但是如果 repository.Foobars
是类型 IEnumerable<Foobar>
,那么它也可以是 Func<Foobar, double>
(它也可以是 Expression<Func<Foobar, double>>
Visual studio 似乎喜欢这个:
public Expression<Func<Foobar, double>> FirstAmountExpr
{
get
{
if (ShouldGetFirstAmount)
{
return x => x.AmountOne;
}
else
{
return x => x.AmountTwo;
}
}
}
public double GetFirstAmount()
{
return repository.Foobars.Select(FirstAmountExpr).First();
}
我不确定我的问题是否有意义,但我们开始吧。我有一个非常复杂的查询,它从依赖运行时变量的 EF 转换为 SQL。
示例:假设我有一个实体对象。
public class Foobar
{
public int ID { get; set; }
public double AmountOne { get; set; }
public double AmountTwo { get; set; }
}
并且我想根据运行时间属性 查询Foobar 的金额字段之一。现在我知道有两种方法可以做到这一点。
方式#1:在代码中
public bool ShouldGetFirstAmount {get; set;}
public double GetFirstAmount()
{
if (ShouldGetFirstAmount)
{
return repository.Foobars.Select(c => c.AmountOne).First();
} else {
return repository.Foobars.Select(c => c.AmountTwo).First();
}
}
优点:sql 查询更小,开销更低 缺点:巨大的代码块/重复
方式 #2:直接在查询中,EF 可以对其进行转换。
public bool ShouldGetFirstAmount {get; set;}
public double GetFirstAmount()
{
return repository.Foobars.Select(c => ShouldGetFirstAmount ? c.AmountOne : c.AmountTwo).First();
}
优点:更小的代码块。 缺点:查询性能因实际查询中的表达式而受到影响
所以我正在寻找第三种方法,让我能够两全其美。我希望能够传入应该计算的实际对象 属性。我只是不确定应该如何完成,或者是否可以完成。
有点像这样的东西。我知道这段代码不起作用,但我想你们明白我想要的想法。
public Expression<double> FirstAmountProperty {get; set;}
public double GetFirstAmount()
{
return repository.Foobars.Select(FirstAmountProperty).First();
}
你很接近。如果 repository.Foobars
是 IQueryable<Foobar>
类型,则表达式需要是 Expression<Func<Foobar, double>>
类型。
但是如果 repository.Foobars
是类型 IEnumerable<Foobar>
,那么它也可以是 Func<Foobar, double>
(它也可以是 Expression<Func<Foobar, double>>
Visual studio 似乎喜欢这个:
public Expression<Func<Foobar, double>> FirstAmountExpr
{
get
{
if (ShouldGetFirstAmount)
{
return x => x.AmountOne;
}
else
{
return x => x.AmountTwo;
}
}
}
public double GetFirstAmount()
{
return repository.Foobars.Select(FirstAmountExpr).First();
}