如何使用表达式树进行内连接(过滤嵌套属性)?

时间:2015-08-19 14:56:36

标签: c# entity-framework inner-join expression-trees

我的用户应该能够配置过滤器以从数据库中获取结果。 我决定使用表达式树,以便灵活处理查询。但是我的表达式树存在问题,无法通过ReferenceCode进行过滤。

实体:

PumpStartUp

  • 持续时间(TimeSpan)

  • DutDbId(Guid / FK)

  • TimeStamp(DateTime)

  • DUT(DeviceUnderTest)

DeviceUnderTest

  • AdminId(字符串/唯一)

  • DbId(Guid / PK)

  • ReferenceCode(string)

  • StartUps(List)

以下是等效linq中过滤器的一部分。但linq我无法使用,因为我不知道用户将定义多少个ReferenceCodes。:

//-------------------reference code filter---------------------------
var query = context.PumpStartUps.Where((p => p.DUT.ReferenceCode == "HKR566" ||
                                             p.DUT.ReferenceCode == "HSH967" ||
                                             .
                                             .
                                             .));
startUps = query.ToList();

对于过滤器的DeviceUnderTest部分进行过滤,我的解决方案是:

// --------------------duts filter-----------------------------------
Expression dutsExpression = null;
Expression psuExpression = Expression.Parameter(typeof(PumpStartUp), "psu");
Expression psuDutIdExpression = Expression.Property(psuExpression, "DutDbId");

foreach (var dut in filter.Duts)
{
    DeviceUnderTest deviceUnderTest = context.DevicesUnderTest.Where(d => d.AdminId == dut.Id).Single();
    Expression dutIdExpression = Expression.Constant(deviceUnderTest.DbId);
    Expression dutExpression = Expression.Equal(pumpStartUpDutIdExpression, dutIdExpression);
    if (dutsExpression == null)
    {
        dutsExpression = dutExpression;
    }
    else
    {
        dutsExpression = Expression.Or(dutsExpression, dutExpression);
    }
}

如何以这种方式按ReferenceCode过滤:

2 个答案:

答案 0 :(得分:1)

使用此:

var dutExpression = Expression.Property(psuExpression, "DUT");
var referenceCodeExp = = Expression.Property(dutExpression, "ReferenceCode ");
var constExpr = Expression.Constant("HKR566");
var eqExp = Expression.Equal(referenceCodeExp , constExpr);
dutsExpression = Expression.Or(dutsExpression, eqExp);

答案 1 :(得分:0)

如果您的代码数量有限,您可以随时说

var query = context.PumpStartUps.Where(p => codes.Contains(p.DUT.ReferenceCode))

直到大约2000个参数才能工作。如果你需要更多,那么你应该以某种方式将代码发送到临时表(或者更确切地说是返回表的函数,因为ef不支持临时表),并且因为构造超过2000次的表达式而不是会表现得很好。