C# 将匹配多个批量输入的LINQ表达式

C# 将匹配多个批量输入的LINQ表达式,c#,entity-framework,linq,C#,Entity Framework,Linq,如何编写匹配多个批量输入的LINQ表达式 这是我的数据库表 Members Division, Department 1 3 4 9 * 5 1 6 3 * 9 2 我要选择标记为的成员* 这是我的意见 int[] divisions = new int[2] {4, 6}; int[] department = new int[2] {9, 3}; 这是我试过的问题

如何编写匹配多个批量输入的LINQ表达式

这是我的数据库表

Members
Division, Department
1           3
4           9       *
5           1
6           3       *
9           2
我要选择标记为的成员*

这是我的意见

int[] divisions = new int[2] {4, 6};
int[] department = new int[2] {9, 3};
这是我试过的问题

var selectedMembers = members.Where(member => divisions.Contains(member.Division) && department.Contains(member.Department)).ToArray();
这在EF中的行为不正确。只有一个输入,而不是两个输入(部门和部门)时,它才起作用 它应该返回输入中匹配的对 例如:

试一试

var member = members.Where(member => divisons.Contains(member.Division) && department.Contains(member.Department)).ToList();

您已经使用了
Select
子句,我已经修改为使用
Where

EF不直接支持这种类型的过滤

一种可能的解决方案是动态构建如下谓词:

member => (member.Division == divisions[0] && member.Department == departments[0])
       || (member.Division == divisions[1] && member.Department == departments[1])
       ...
       || (member.Division == divisions[N-1] && member.Department == departments[N-1]);
以下是如何做到这一点:

var parameter = Expression.Parameter(typeof(Member), "member");
var predicate = Expression.Lambda<Func<Member, bool>>(
    Enumerable.Range(0, divisions.Length)
    .Select(i => new Expression[]
    {
        Expression.Equal(Expression.Property(parameter, "Division"), Expression.Constant(divisions[i])),
        Expression.Equal(Expression.Property(parameter, "Department"), Expression.Constant(departments[i])),
    }
    .Aggregate(Expression.AndAlso))
    .Aggregate(Expression.OrElse),
    parameter);
var query = members.Where(predicate);
var参数=表达式参数(typeof(Member),“Member”);
var谓词=表达式.Lambda(
可枚举。范围(0,分段。长度)
.选择(i=>newexpression[]
{
Expression.Equal(Expression.Property(参数“除法”)、Expression.Constant(除法[i])、Expression,
Expression.Equal(Expression.Property(参数,“Department”)、Expression.Constant(departments[i])、Expression,
}
.合计(表示为AndAlso))
.骨料(表示为OrElse),
参数);
var query=members.Where(谓词);

这与@Robert的答案类似,但会过滤结果,以确保部门和部门是相同的“一对”:


.Zip()
是否在实体框架中工作?您需要查询属于任何列出的部门和部门的成员?@Robert yes。是否可以使用EF?
。Select
是一个未经筛选的选择,允许您进行转换-您需要使用
。Where
是一个过滤的选择,没有转换(您似乎不需要)。这是一个打字错误,应该是。如果是打字错误,就应该是。Where@Jasmine,它现在工作了吗?与OP查询有什么区别(除了
ToList
而不是
ToArray
?@Phil1970 OP修改的问题。原始问题中的OP user Select子句见Renan Araújo和我之间的讨论。你的答案也是如此。还有更多,因为你不能在EF LINQ查询中使用
Enumerable.Range
。@GertArnold谢谢。是否使用
加入
或Robert的答案将所有成员也加载到内存中?好吧,这不是关于将数据加载到内存中,EF(6)不会自动这样做。查询不会运行。Robert的答案(包含)将正确地转换为在
子句中包含
的SQL查询,但结果不正确,因为它还将返回其他组合,如记录第4部分第3部分(如果存在)。两个单独的联接将显示相同的缺陷。@GertArnold在其问题的注释中,OP表示他希望“查询属于任何列出的部门和部门的成员”。答案是“是”"对于一个问题,他们可能会有不同的解释。问题在于将查询限制在特定的组合中,否则Ivan的答案不会被接受。你对问题的解释是正确的。从性能角度来看,这个解决方案的效率如何?问得好。我认为它应该与
包含的
哪个翻译相比较在(…)
中添加到SQL
。如果列表很大,则会出现相同的问题。您需要尝试查看。问题是,即使使用原始SQL,您似乎也没有其他选择。但多亏了@Gert Arnold,您可以查看他的答案,其中提供了对问题的更完整分析。
var parameter = Expression.Parameter(typeof(Member), "member");
var predicate = Expression.Lambda<Func<Member, bool>>(
    Enumerable.Range(0, divisions.Length)
    .Select(i => new Expression[]
    {
        Expression.Equal(Expression.Property(parameter, "Division"), Expression.Constant(divisions[i])),
        Expression.Equal(Expression.Property(parameter, "Department"), Expression.Constant(departments[i])),
    }
    .Aggregate(Expression.AndAlso))
    .Aggregate(Expression.OrElse),
    parameter);
var query = members.Where(predicate);
int[] divisons = { 4, 6 }, departments = { 9, 3 };
var members = new[] { new { Division = 1, Department = 2 } }; // just for testing

var query = members.Where(m => divisons.Contains(m.Division) 
                         && departments.Contains(m.Department));

var member = query.AsEnumerable().Where(m => Array.IndexOf(divisons, m.Division) 
                        == Array.IndexOf(departments, m.Department));