我试图更好地理解更复杂的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。
为什么查询和qry都超出范围?我宁愿只在我的方法中返回linq语句,而不必解析一个对象以获取要返回的列表。一篇讨论这个问题的文章将是很棒的。
尽管有一个可以解决根本问题并使查询正常运行的答案,但实际的问题尚未得到答案。为什么变量超出范围的问题的答案可能会帮助您更好地理解LINQ。
该声明...
from query in _context.WebQueries select query
可以改写为:
_context.WebQueries.Select(query => query)
(该部分.Select(query => query)
是多余的,但为了解释起见,我将其留在此处)
可以使用方法主体将此语句重写为lambda表达式:
WebQueries.Select(query => { return query; })
(我将在后面解释为什么我不再使用_context.WebQueries
了)
可以使用匿名方法将其重写为表达式:
WebQueries.Select(delegate(WebQuery query) { return query; })
可以使用命名方法将其重写为表达式:
WebQueries.Select(ReturnArg)
ReturnArg
该方法在哪里:
WebQuery ReturnArg(WebQuery query)
{
return query;
}
这是相反的C#历史记录:我们过去只具有命名方法和委托。后来,为了实现LINQ和其他功能,引入了匿名方法和lambda表达式。但是这里要注意的是,对于编译器来说,方法语法仍然适用,因此lambda表达式query => query
不过是带有名为的参数的方法而已query
。与所有方法一样,参数的作用域为方法主体。
在LINQ术语中,此参数称为范围变量,因为它将用作对查询中每个连续元素的引用。
简而言之:range变量的作用域为定义该变量的LINQ语句。(from query in _context.WebQueries select query)
是一条LINQ语句。后续Where
是新的LINQ语句。
我停止使用的原因_context.WebQueries
是EF不接受带有方法主体的lambda表达式。这是因为方法主体将方法的参数Where
从表达式无声地转换为Func
,而EF仅接受表达式。实际上,整个语句永远不会在CLR中执行,而是转换为SQL并由数据库引擎执行。但是,对于C#编译器,正确性规则仍然适用。范围变量是范围变量,无论其用途是什么。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句