在 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.FoobarsIQueryable<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();
}