我有一对N对整数的列表,例如:
2, 4
5, 7
9, 10
11, 12
我需要构建一个类似的查询:
WHERE
(foo = 2 AND bar = 4) OR
(foo = 5 AND bar = 7) OR
(foo = 9 AND bar = 10) OR
(foo = 11 AND bar = 12)
如果它是一个恒定长度列表,我可以写一些像:
var query = myClass.Where(x =>
(foo == values[0][0] && bar == values[0][1]) ||
(foo == values[1][0] && bar == values[1][1]) ||
(foo == values[2][0] && bar == values[2][1]) ||
(foo == values[3][0] && bar == values[3][1]));
但是列表的长度各不相同,我正在寻找一种使用循环创建查询的方法。
我发现我可以使用Queryable.Union()
获得类似的结果,但考虑到查询中有更多条件,并且对的列表可能很长,我宁愿避免 union
这个问题有解决办法吗?
答案 0 :(得分:2)
您可以执行一项操作 - 连接查找字段:bar
和Contains
,然后使用var filters = new int[][] {
new int[] { 2, 4 },
new int[] { 5, 7 },
new int[] { 9, 10 },
new int[] { 11, 12 }
};
var newFilter = filters.Select(x => x[0] + "-" + x[1]).ToList();
var answer = dbContext.myClass.Where(x => newFilter.Contains(x.foo + "-" + x.bar)).ToList();
方法:
ref.observeEventType(.Value, withBlock: {
snapshot in let m = snapshot.value.objectForKey("users/\(self.ref.authData.uid)/email") as? String
self.EmailLabel.text = m
})
答案 1 :(得分:1)
假设values
是一个锯齿状数组,myClass
是IEnumerable<T>
个具有foo
和bar
属性的对象:
var query = myClass.Where(x => values.Any(y => x.foo == y[0] && x.bar == y[1]));
针对Any
中每个对象运行的内部myClass
语句,查找values
中任何内容与foo
和{{1}匹配的“行” } bar
的属性。本质上,myClass
子句迭代表中的每一行,而Any
子句迭代(并过滤)Where
中的每个对象。
但是,我不知道它会比使用myClass
效率更多。
如评论中所述,此方法不适用于LINQ to Entities。通过从数据库中提取所有记录并在内存中过滤它们,它仍然可以与Entity Framework结合使用,但显然这不是一个有效的解决方案。
答案 2 :(得分:0)
试试这个:
var query = myClass.Where(x => x.Any(p => p[0] == foo && p[1] == bar));
答案 3 :(得分:0)
取整数集并将其制作成地图。然后使用LINQ测试.Any
。
var map = new Dictionary<int, int>()
{
{2, 4},
{5, 7},
{9, 10},
{11, 12}
};
var foo = 2;
var bar = 4;
var q = map.Any(kv => foo == kv.Key && bar == kv.Value);
或者,您可以获取int对列表并将它们放入Tuple<int, int>
列表中并测试foo和bar,如下所示:
var q = listOfTuples.Any(tp => foo == tp.Item1 && bar == tp.Item2);
这里的要点是你需要获取“一对一对的列表”并决定如何构建这些信息。一旦你拨打电话,其他一切都将落实到位。一步一步,对吗? :-)
答案 4 :(得分:0)
我根据Dynamic Queries in Entity Framework using Expression Trees
中描述的类似解决方案找到了解决此问题的方法这是解决方案。
首先,一个持有 foo 和 bar 对的类:
public class FooBarPair
{
public int Foo { get; set; }
public int Bar { get; set; }
}
然后, foos 和吧的集合:
var pairs = new FooBarPair[]
{
new Foo() { Foo = 10537, Bar = 1034 },
new Foo() { Foo = 999, Bar = 999 },
new Foo() { Foo = 888, Bar = 888 },
new Foo() { Foo = 10586, Bar = 63 },
};
以下是构建查询表达式的代码:
public static void Main()
{
Expression<Func<MyClass, bool>> whereClause =
BuildOrExpressionTree<MyClass, int>(pairs, m => m.Foo + m.Bar);
var myClasss = model.Set<MyClass>();
IQueryable<MyClass> query = myClasss.Where(whereClause);
}
/// <summary>
/// Starts a recursion to build WHERE (m.Foo = X1 AND m.Bar = Y1) [OR (m.Foo = X2 AND m.Bar = Y2) [...]].
/// </summary>
private static Expression<Func<TValue, bool>> BuildOrExpressionTree<TValue, TCompareAgainst>(
IEnumerable<FooBarPair> wantedItems,
Expression<Func<TValue, TCompareAgainst>> convertBetweenTypes1)
{
ParameterExpression inputParam1 = convertBetweenTypes1.Parameters[0];
BinaryExpression binaryExpression = convertBetweenTypes1.Body as BinaryExpression;
Expression binaryExpressionTree = BuildBinaryOrTree<FooBarPair>(
wantedItems.GetEnumerator(),
binaryExpression.Left,
binaryExpression.Right,
null);
return Expression.Lambda<Func<TValue, bool>>(binaryExpressionTree, new[] { inputParam1 });
}
/// <summary>
/// Recursive function to append one 'OR (m.Foo = X AND m.Bar = Y)' expression.
/// </summary>
private static Expression BuildBinaryOrTree<T>(
IEnumerator<FooBarPair> itemEnumerator,
Expression expressionToCompareTo1,
Expression expressionToCompareTo2,
Expression prevExpression)
{
if (itemEnumerator.MoveNext() == false)
{
return prevExpression;
}
ConstantExpression fooConstant = Expression.Constant(itemEnumerator.Current.Foo, typeof(int));
ConstantExpression barConstant = Expression.Constant(itemEnumerator.Current.Bar, typeof(int));
BinaryExpression fooComparison = Expression.Equal(expressionToCompareTo1, fooConstant);
BinaryExpression barComparison = Expression.Equal(expressionToCompareTo2, barConstant);
BinaryExpression newExpression = Expression.AndAlso(fooComparison, barComparison);
if (prevExpression != null)
{
newExpression = Expression.OrElse(prevExpression, newExpression);
}
return BuildBinaryOrTree<FooBarPair>(
itemEnumerator,
expressionToCompareTo1,
expressionToCompareTo2,
newExpression);
}
谢谢大家!