C#,Linq2Sql:是否可以将两个可查询连接成一个?

我有一个可查询的地方,我使用各种WhereWhereBetween语句将集合缩小到某个集合。 现在我需要添加一个Where || WhereBetween Where || WhereBetween 。 换句话说,我不能像现在一样把它们连在一起,因为它可以作为一个And。 那么,我该怎么做呢?

我看到两种可能性:

  1. 从我拥有的一个查询中创建两个查询 ,一个使用Where ,一个使用WhereBetween然后将它们连接起来 。 不知道这是否可能? 此外,虽然不是在我的特定情况下,你很可能最终会重复…
  2. 以某种方式合并Where表达式和WhereBetween创建的表达式

首先,如上所述,我不确定是否可能。 如果是的话,我不太确定这是一个很好的方法。

第二,我可以看到一个选项,但不完全确定所有的细节。 下面是我的另一个问题中的WhereBetween方法,我现在使用它并且效果很好:

  public static IQueryable WhereBetween( this IQueryable source, Expression<Func> selector, IEnumerable<Range> ranges) { var param = Expression.Parameter(typeof(TSource), "x"); var member = Expression.Invoke(selector, param); Expression body = null; foreach (var range in ranges) { var filter = Expression.AndAlso( Expression.GreaterThanOrEqual(member, Expression.Constant(range.A, typeof(TValue))), Expression.LessThanOrEqual(member, Expression.Constant(range.B, typeof(TValue)))); body = body == null ? filter : Expression.OrElse(body, filter); } return body == null ? source : source.Where( Expression.Lambda<Func>(body, param)); } 

我想我可以将它的表达式构建部分提取到一个新方法中。 也许是这样的:

  public static IQueryable WhereBetween( this IQueryable source, Expression<Func> selector, IEnumerable<Range> ranges) { return source.Where(WhereBetween(selector, ranges)); } public static Expression<Func> WhereBetween( Expression<Func> selector, IEnumerable<Range> ranges) { var param = Expression.Parameter(typeof(TSource), "x"); var member = Expression.Invoke(selector, param); Expression body = null; foreach (var range in ranges) { var filter = Expression.AndAlso( Expression.GreaterThanOrEqual(member, Expression.Constant(range.A, typeof(TValue))), Expression.LessThanOrEqual(member, Expression.Constant(range.B, typeof(TValue)))); body = body == null ? filter : Expression.OrElse(body, filter); } return body == null ? ø => true : Expression.Lambda<Func>(body, param); } 

然后我可以使用该新方法来获取表达式而不是可查询表达式。 所以,假设我有WhereBetween(ø => ø.Id, someRange) ,例如ø => ø.SomeValue == null 。 我如何将这两者与Or结合起来? 我正在查看WhereBetween方法中使用的Expression.OrElse ,我认为这可能是我需要的,或者也许是Expression.Or 。 但是我对这些表达方式非常不稳定,所以我不确定在这里选择什么,或者即使我在正确的轨道上:p

有人可以给我一些指示吗?

这里有两个选项 – Queryable.Union或表达式组合。 我通常喜欢后者,通过OrElse – 它(至少使用LINQ-to-SQL)你可以使用2个表达式(见下文) – 但在任何一种情况下都应该得到组合:

  using(var ctx = new DataClasses1DataContext()) { ctx.Log = Console.Out; Expression> lhs = x => x.Country == "UK"; Expression> rhs = x => x.ContactName.StartsWith("A"); var arr1 = ctx.Customers.Where( lhs.OrElse(rhs)).ToArray(); var arr2 = ctx.Customers.Where(lhs) .Union(ctx.Customers.Where(rhs)).ToArray(); } 

arr1arr2都只执行1次数据库命中(尽管TSQL不同;第一个在WHERE子句中有OR ;第二个在UNION有两个单独的查询)。

这是我使用的扩展方法:

 static Expression> OrElse( this Expression> lhs, Expression> rhs) { var row = Expression.Parameter(typeof(T), "row"); var body = Expression.OrElse( Expression.Invoke(lhs, row), Expression.Invoke(rhs, row)); return Expression.Lambda>(body, row); }