当前上下文中不存在名称为'con'的内容。

3

我正在尝试使用LINQ创建一个分组语句。但是出现了错误:“The name 'con' does not exist in the current context.”

在我的代码中,在执行select之后,我试图获取ActivityID的值,但是列表“con”不可用。

List<Contribution> contributions =
    contLogic.GetAllContibutionsByActivityIDToList(ActivityID);

var groups = from con in contributions
             group con by con.Response
             into gResponse
             select new
             {
                grop = gResponse.Count(),
                con.ActivityID
             };

我查看了微软的示例,但不知道我做错了什么。

微软示例:

List<Product> products = GetProductList();

var orderGroups = from prod in products
                  group prod by prod.Category into prodGroup
                  select new { Category = prodGroup.Key, Products = prodGroup };

ObjectDumper.Write(orderGroups, 1);

你在哪里实例化CON? - Mark Kram
4个回答

19

into子句是一个查询续延子句。查询续延会从作用域中删除所有先前的范围变量,然后引入新的范围变量

这可能不是非常清晰。让我举个例子来更好地说明它。

我有棕色的眼睛;我妹妹有蓝色的眼睛。假设我们想找到像我一样的人:拥有蓝眼睛兄弟姐妹的棕眼睛人。我们可以这样做:

var parentsWithABlueEyedChild = 
    from parent in parents 
    where parent.Children.Any(c=>c.EyeColor == Blue) 
    select parent;

var brownEyedChildren = 
    from parentWithABlueEyedChild in parentsWithABlueEyedChild
    from child in parentWithABlueEyedChild.Children 
    where child.EyeColor == Brown 
    select child;

好的,你有两个查询。第二个查询操作的是第一个查询的结果。现在,你认为“parent”在第二个查询中不在范围内,对吗?“parent”区域变量只有在声明它的查询中才有意义。

你可以将这两个查询合并成一个查询,如下所示:

var brownEyedChildren = 
    from parentWithABlueEyedChild in (
        from parent in parents 
        where parent.Children.Any(c=>c.EyeColor == Blue) 
        select parent)
    from child in parentWithABlueEyedChild.Children 
    where child.EyeColor == Brown 
    select child;

看起来,"parent" 只在 "inner" 查询中有效,对吗?

但是与第一种语法相比,这种语法难以阅读;为什么要在使用三行之前引入 "parentWithABlueEyedChild"?第一种版本更清晰。我们可以使用查询延续将其转换为一个查询,同时保持第一种版本的可读性:

var brownEyedChildren = 
    from parent in parents 
    where parent.Children.Any(c=>c.EyeColor == Blue) 
    select parent into parentWithABlueEyedChild
    from child in parentWithABlueEyedChild.Children 
    where child.EyeColor == Brown 
    select child;

这与前两个版本完全相同。继续语句只是一种方便的写法。parent在继续子句中不在作用域内,因为如果将它们作为两个查询编写,它也不会在作用域内。

现在你明白了吗,为什么你的续集中 "con" 不在作用域内吗?

var q = 
    from con in contributions
    group con by con.Response
    into gResponse
    select new 
    {
        grop = gResponse.Count(),
        con.ActivityID
    }; 

完全相同

var gResponses = 
    from con in contributions
    group con by con.Response;
var q =
    from gResponse in gResponses
    select new 
    {
        grop = gResponse.Count(),
        con.ActivityID
    }; 

"con" 在第二个查询中不在作用域内,它只是第一个查询的一部分。


3
这是一个很好的例子来解释这个概念。虽然我理解了这个概念,但我不知道该如何向别人解释。现在我可以把这个答案转给他们。Eric,显然你是一个优秀的程序员,但我个人觉得你更是一个出色的教师/沟通者。谢谢你的教导。 - SolutionYogi
@SolutionYogi:感谢你的赞美之词,我很感激。 - Eric Lippert

10

con在你的分组范围之外。请注意,在Microsoft的示例中,他们最初的查询元素是prod,但在分组后,他们引用了prodGroup

你的查询基于共同的Response将元素分组在一起,实际上是为了更大的整体"失去"了单独的con。你可能需要扩展你的分组,以包括比Response更多的标准,比如

group by new { con.Response, con.ActivityID }

然后通过 ID 引用:

gResponse.Key.ActivityID

或者访问每个组中第一个元素的ActivityID

gResponse.First().ActivityID

如果你没有提供更多关于你想要实现什么的信息,我就不能为你提供具体的建议以指导你的下一步行动。


在 .First() 的例子上做得很好。我没有意识到这是可能的。我能够使用这种方法有条件地检查我的组投影中的值。 - SwampyFox

1

由于作用域的限制,您无法在新构造函数中访问con。您需要使用gResponse来访问所需的数据。

gResponse视为您的部分总和;确保它包括您在执行select new时需要访问的所有内容。


0
一旦你完成了一个group <something> by <function of something> into <group_variable>,你原来的范围变量<something>就不再可用了 - 所有的something都被分组到group_variable中,所以这就是所有要讨论的内容。
在你的例子中,你开始有很多贡献,但是然后你将它们分组 - 现在你有了很多groups,每个group都有一个Key(用于分组的Response)和一系列的贡献。如果你愿意采用组中第一个贡献的ActivityID(我不知道这对你是否有意义),你可以这样做:
select new
{
    grop = gResponse.Count(),
    ActivityID = gResponse.First().ActivityID
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接