我需要通过比较一系列int数据来执行带有where子句的查询。
例如:
class RangeClass
{
public int From{get; set;}
public int To {get; set;}
}
void ExecuteQuery()
{
// prepare a list of range data
List<RangeClass> rangeList = new List<Range>();
rangeList .Add(new rangeClass ...
rangeList .Add(new RangeClass ...
DbContext db = new DbContext();
var query = db.Invoice.Where(p => rangeList.Any(x => p.Price >= x.From && p.Price <= x.To)).ToList();
}
显然,由于我在查询中使用的非原始类型(RangeClass),我得到了NotSupportedExcetpion。
是否有一些解决方法可以使用Linq To Entities完成我的查询?
@@ EDIT
为了澄清我的例子,这里有一些信息:
RangeClass List (in memory list):
1 - From = 1; To = 10;
2 - From = 20; To = 30;
3 - From = 31; To = 40;
发票数据库记录:
1 - Price = 5;
2 - Price = 15;
3 - Price = 20;
我的查询应该返回发票表的第一个(价格5)和最后一个(价格20)记录,因为第二个(价格15)不在我的记忆列表中的任何“记录”之间。
答案 0 :(得分:2)
由于范围比较可以用以下表达式替换:
_.Price >= r1.From && _.Price <= r1.To ||
_.Price >= r2.From && _.Price <= r2.To ||
...
_.Price >= rN.From && _.Price <= rN.To
您可以动态构建此表达式:
static class RangeHelpers
{
public static IQueryable<T> PropertyFitsAnyRange<T, TProperty>(this IQueryable<T> query, IEnumerable<Range> ranges, Expression<Func<T, TProperty>> propertyToCompareExpr)
{
Expression conditionalExpr = null;
foreach (var range in ranges)
{
var andExpr = Expression.And(
Expression.GreaterThanOrEqual(propertyToCompareExpr.Body, Expression.Constant(range.From)),
Expression.LessThanOrEqual(propertyToCompareExpr.Body, Expression.Constant(range.To)));
conditionalExpr = conditionalExpr == null ? andExpr : Expression.Or(conditionalExpr, andExpr);
}
if (conditionalExpr != null)
{
query = query
.Where(Expression.Lambda<Func<T, bool>>(conditionalExpr, propertyToCompareExpr.Parameters[0]));
}
return query;
}
}
用法:
var invoices = context
.Invoices
.PropertyFitsAnyRange(ranges, _ => _.Price);
P.S。我相信,Invoice.Price
是十进制的。如果是这样,Range
类定义应为:
public class Range
{
public decimal From { get; set; }
public decimal To { get; set; }
}