编辑:试图让我的问题更加明确。
我正在尝试构建一个LINQ表达式,它是几个LINQ语句的交集。现在,手动我可以将两个语句交叉在一起,我得到了理想的结果。
var results =
context.UserBooleanAttributes.Where(x => x.UserAttributeID == 1 && x.Value).Select(a => a.User)
.Intersect(
context.UserBooleanAttributes.Where(y => y.UserAttributeID == 2 && y.Value).Select(b => b.User)
);
Assert.Equal(100,results.Count());
我的目标是动态构建它,例如使用for循环。由于我使用LINQ,我想推迟执行,直到我实际调用强制执行的结果。
答案 0 :(得分:1)
您似乎只需要User
的列表:
var list = new List<User>();
然后你可以添加每组结果:
list.AddRange(someUsers);
如果User
是一个可以执行Intersect
的类,并且您只需要不同的值(在您的代码中似乎就是这种情况),请考虑一次性执行,并调用最后Distinct()
:
var attrIDs = Enumerable.Range(1, xTimes);
list.AddRange(context.UserBooleanAttributes
.Where(x => attrIDs.Contains(x.UserAttributeID) && x.Value)
.Select(a => a.User)
.Distinct());
答案 1 :(得分:1)
您的代码可以重构,以获取多个用户列表:
IEnumerable<IEnumerable<User>> GetListOfListsOfUsers(int xTimes)
{
for (int i = 1; i <= xTimes; i++)
{
var someUsers = context.UserBooleanAttributes
.Where(x => x.UserAttributeID == i && x.Value == true)
.Select(a => a.User);
yield return someUsers;
}
}
var listOfListsOfUsers = GetListOfListsOfUsers(xTimes);
现在问题变为intersection of multiple lists:
var intersection = listOfListsOfUsers.Aggregate((previousList, nextList) => previousList.Intersect(nextList));
答案 2 :(得分:0)
这里有几个问题。第一个是我需要一种方法来声明我的匿名变量以便在循环之外使用。我通过使用 IQueryable allBooleansTrue 来做到这一点。我为它赋予了一个非空值,让Resharper不再唠叨我。第二个问题是我遇到的是着名的closures issue。我使用 int copy = i
解决了这个问题 IQueryable<User> allBooleansTrue = new List<User>().AsQueryable();
for (int i = 1; i <= numBools; i++)
{
int copy = i; //workaround to prevent closures using reference
var q = context.UserBooleanAttributes.Where(y => y.UserAttributeID == copy && y.Value)
.Select(a => a.User);
if (i == 1)
allBooleansTrue = q;
else
allBooleansTrue = allBooleansTrue.Intersect(q);
第一次迭代用LINQ语句替换外部变量(allBooleansTrue)的内容。其他迭代执行交叉。这里有点hacky,但这似乎有效(到目前为止)。我想我应该使用表达式树,但那是另一天。
抱歉,我原来的帖子稍微改了一下我的代码,但是我已经厌倦了并且从我的测试班中复制了这个。