生成具有多个OR语句的实体框架查询

时间:2018-11-05 08:10:50

标签: c# entity-framework tuples

当前,我有一个列表(List<Tuple<DateTime, DateTime>>)代表时间范围列表。 现在,我想创建一个通用列表,从中选择这些范围内的所有记录。

List<Tuple<DateTime, DateTime>> ranges = new List<Tuple<DateTime, DateTime>>{
    new Tuple<DateTime, DateTime(new Date(2018,01,01), new Date(2019,01,01)}

IQueryable<item> items = context.items.Where(e => e.category.equals("somecategory"));

ranges.ForEach((Tuple<DateTime, DateTime) range => { 
     items = items.Where(e => e.date >= range.Item1 && e.date <= range.Item2); 
})

最后一个循环应使用“ OR”扩展语句,以便具有

.Where(e => e.date between range1 || e.date between range2 || ...).

有什么聪明的解决方案吗?

3 个答案:

答案 0 :(得分:1)

Tuple可以直接在Where子句中使用,例如

var result = (from i in items
              from r in ranges
              where i.date >= r.Item1 && i.date <= r.Item2
              select i).ToList();

答案 1 :(得分:0)

您应该使用Expression动态创建lambda表达式,例如:

List<Person> totalPerson = new List<Person> {
    new Person{  Id = 1,CreateTime = new DateTime(2018,10,2)},
    new Person{  Id = 2,CreateTime = new DateTime(2018,10,3)},
    new Person{  Id = 3,CreateTime = new DateTime(2018,10,4)},
    new Person{  Id = 4,CreateTime = new DateTime(2018,10,6)},
    new Person{  Id = 5,CreateTime = new DateTime(2018,10,7)},
    new Person{  Id = 6,CreateTime = new DateTime(2018,10,8)},
    new Person{  Id = 7,CreateTime = new DateTime(2018,10,11)},
    new Person{  Id = 8,CreateTime = new DateTime(2018,10,12)},
    new Person{  Id = 9,CreateTime = new DateTime(2018,10,13)},
    new Person{  Id = 10,CreateTime = new DateTime(2018,10,16)},
    new Person{  Id = 11,CreateTime = new DateTime(2018,10,17)},
    new Person{  Id = 12,CreateTime = new DateTime(2018,10,18)}
};
List<Tuple<DateTime, DateTime>> ranges = new List<Tuple<DateTime, DateTime>>{
    new Tuple<DateTime, DateTime>(new DateTime(2018,10,1), new DateTime(2018,10,5)),
    new Tuple<DateTime, DateTime>(new DateTime(2018,10,10), new DateTime(2018,10,15))
};

IQueryable<Person> persons = totalPerson.Where(t => t.Id > 0).AsQueryable();
var parameter = Expression.Parameter(typeof(Person), "t");
BinaryExpression binaryExpression = null;

ranges.ForEach(range =>
{
    MemberExpression filed = Expression.PropertyOrField(parameter, "CreateTime");
    var startTime = Expression.Constant(range.Item1);
    var endTime = Expression.Constant(range.Item2);
    var expressionItem1 = Expression.GreaterThanOrEqual(filed, startTime);
    var expressionItem2 = Expression.LessThanOrEqual(filed, endTime);
    var expressionItem = Expression.And(expressionItem1, expressionItem2); ;
    if (binaryExpression == null)
    {
        binaryExpression = expressionItem;
    }
    else
    {
        binaryExpression = Expression.Or(binaryExpression, expressionItem);
    }
});
Expression<Func<Person, bool>> condition = Expression.Lambda<Func<Person, bool>>(binaryExpression, parameter);

var results = persons.Where(condition);

答案 2 :(得分:0)

由于我的限制,我们的Entity Framework版本无法处理元组,因此我使用Union解决了该问题:

public List<MyObject> GetList(Item item){
    IQueryable<MyObject> qMyobjects = this.GetQueryableList(item, item.ranges.first().item1, item.ranges.first().item2;

    item.ranges.Skip(1).ToList().ForEach((Tuple<DateTime, DateTime> range) => {
        IQueryable<MyObject> select = this.GetQueryableList(item, range.item1, range.item2);
        qMyobjects = qMyobjects.Union(select);
    });
    return qMyobjects.ToList();
}

protected IQueryable<MyObject> GetQueryableList(Item item, DateTime dateFrom, DateTime dateTo){
    return _context.myobjects
        .Where(e => e.category.Equals("somecategory")
        .Where(e => e.date >= dateFrom && e.date <= dateTo);
}