如何在运行时动态组合一组LINQ查询?

时间:2015-07-22 02:41:53

标签: c# linq resharper

编辑:试图让我的问题更加明确。

我正在尝试构建一个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,我想推迟执行,直到我实际调用强制执行的结果

3 个答案:

答案 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,但这似乎有效(到目前为止)。我想我应该使用表达式树,但那是另一天。

抱歉,我原来的帖子稍微改了一下我的代码,但是我已经厌倦了并且从我的测试班中复制了这个。