如何使用表达式树进行内部连接(过滤嵌套属性)?
How to inner join(filtering for nested properties) with expression tree?
我的用户应该能够配置过滤器以从数据库中获取结果。
我决定使用表达式树,以便灵活地处理查询。但是我对通过 ReferenceCode 过滤的表达式树有问题。
实体:
泵启动
持续时间(时间跨度)
DutDbId (Guid/FK)
时间戳(日期时间)
DUT(待测设备)
待测设备
AdminId (string/unique)
DbId (Guid/PK)
参考代码(字符串)
初创公司(列表)
这是等效 linq 中过滤器的一部分。但是linq我不能用,因为我不知道用户会定义多少ReferenceCodes。:
//-------------------reference code filter---------------------------
var query = context.PumpStartUps.Where((p => p.DUT.ReferenceCode == "HKR566" ||
p.DUT.ReferenceCode == "HSH967" ||
.
.
.));
startUps = query.ToList();
对于通过DeviceUnderTest部分filter进行过滤,我的解决方案是:
// --------------------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 进行过滤:
使用这个:
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);
如果代码量有限,可以随时说
var query = context.PumpStartUps.Where(p => codes.Contains(p.DUT.ReferenceCode))
这可以工作到大约 2000 个参数。如果您需要更多,那么您应该以某种方式将代码发送到临时 table(或者更确切地说是返回 table 的函数,因为 ef 不支持临时 tables),然后加入因为构建一个超过 2000 or 的表达式不会有很好的表现。
我的用户应该能够配置过滤器以从数据库中获取结果。 我决定使用表达式树,以便灵活地处理查询。但是我对通过 ReferenceCode 过滤的表达式树有问题。
实体:
泵启动
持续时间(时间跨度)
DutDbId (Guid/FK)
时间戳(日期时间)
DUT(待测设备)
待测设备
AdminId (string/unique)
DbId (Guid/PK)
参考代码(字符串)
初创公司(列表)
这是等效 linq 中过滤器的一部分。但是linq我不能用,因为我不知道用户会定义多少ReferenceCodes。:
//-------------------reference code filter---------------------------
var query = context.PumpStartUps.Where((p => p.DUT.ReferenceCode == "HKR566" ||
p.DUT.ReferenceCode == "HSH967" ||
.
.
.));
startUps = query.ToList();
对于通过DeviceUnderTest部分filter进行过滤,我的解决方案是:
// --------------------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 进行过滤:
使用这个:
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);
如果代码量有限,可以随时说
var query = context.PumpStartUps.Where(p => codes.Contains(p.DUT.ReferenceCode))
这可以工作到大约 2000 个参数。如果您需要更多,那么您应该以某种方式将代码发送到临时 table(或者更确切地说是返回 table 的函数,因为 ef 不支持临时 tables),然后加入因为构建一个超过 2000 or 的表达式不会有很好的表现。