我正在尝试更好地理解更复杂的 linq 语句。多亏了网络上的几篇文章,我才有所了解。我不明白的一件事是为什么我的查询别名在此语句中脱离上下文:
(from query in _context.WebQueries
select query).Where((from qry in _context.WebQueries
join qg in _context.WebQueryGroups on qry.QueryKey equals qg.QueryKey
where qg.QueryGroupNameKey == key
//This is out of scope
select qry.QueryKey).Contains(query.QueryKey));
//if you replaced it with this same problem
.Contains(qry.QueryKey));
我知道我可以使用匿名对象调用并获得我想要的结果。我只需要迭代对象并拉出我想要的列表:
(from query in _context.WebQueries
select new {query, key = query.QueryKey})
.Where(q => !(from qry in _context.WebQueries
join qg in _context.WebQueryGroups on qry.QueryKey equals qg.QueryKey
where qg.QueryGroupNameKey == key
select qry.QueryKey).Contains(q.key));
这会返回一个对象,其中包含我想要的列表和我想稍后在查询中引用的 int。
为什么 query 和 qry 都超出了范围?我宁愿只在我的方法中返回 linq 语句,而不必解析对象来获取要返回的列表。讨论这个问题的文章会很棒。
最佳答案
我注意到您没有得到您具体问题的答案,据我了解,这是“查询中的范围规则是什么?”
首先,让我们仔细定义“范围”。实体的范围是程序文本的一个区域,其中可以通过非限定名称引用特定实体。
了解范围变量作用域的关键是了解编译器如何翻译查询。这是一个句法翻译。当你说:
from r in s where t select u
编译器在句法上将其翻译成:
((s).Where(r => t)).Select(r => u)
在翻译版本中有两个 r
,都是 lambda 形式参数,并且适用 lambda 的常规范围规则;每个仅在 lambda 主体的范围内。
现在您知道为什么不能在查询之外使用范围变量了;该范围变量实际上是一个或多个 lambda 的形式参数,因此仅在这些 lambda 的主体中有效。
您可以通过阅读有关查询翻译的 C# 规范部分来了解其余规则。我注意到“透明标识符”查询的规则具有棘手的范围界定,因此请仔细阅读该部分。我一直想就此写一篇博客文章。
更新:我开始写那篇博文;你可以在这里阅读:
http://ericlippert.com/2014/07/31/transparent-identifiers-part-one/
http://ericlippert.com/2014/08/01/transparent-identifiers-part-two/
关于c# - 为什么我的 linq 别名超出范围?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24995477/