Linq To Entities没有原始类型

时间:2014-12-15 09:13:55

标签: c# linq-to-entities

我需要通过比较一系列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)不在我的记忆列表中的任何“记录”之间。

1 个答案:

答案 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; }
}