在2.2版中,我可以这样写:
List<Claim> claims = new List<Claim>();
var userRoles = await _userManager.GetRolesAsync(user);
foreach (var role in _roleManager.Roles.Where(a => userRoles.Contains(a.Name)))
{
claims.AddRange(await _roleManager.GetClaimsAsync(role));
}
return claims;
在3.1中,它给了我这个错误:
System.InvalidOperationException:已经有与此命令关联的打开的DataReader,必须先关闭它。
但是,如果我添加
ToList()
对于forEach子句,它可以正常工作(像这样):
List<Claim> claims = new List<Claim>();
var userRoles = await _userManager.GetRolesAsync(user);
foreach (var role in _roleManager.Roles.Where(a => userRoles.Contains(a.Name)).ToList())
{
claims.AddRange(await _roleManager.GetClaimsAsync(role));
}
return claims;
我应该在代码中更改使用相似构造的所有位置,还是有办法使EF正常工作?
答案 0 :(得分:1)
为什么ToList()
有效?
为什么不添加ToList()就抛出期望值?
更新
3.0之前的EF的较旧版本无法将表达式转换为SQL或参数,并且它会自动在客户端评估LINQ表达式,但是EF的新版本允许在查询的最后select
次调用中使用表达式,因此如果在其他表达式中查询的一部分无法转换为SQL或参数,然后引发异常
来源Microsoft文档,可以阅读更多here
答案 1 :(得分:0)
因为_roleManager.Roles.Where(a => userRoles.Contains(a.Name)
创建了一个IEnumerator,当它尝试进行连接时
再次执行await _roleManager.GetClaimsAsync(role)
。发现它已经有一个
open DataReader associated
3.0可能执行了内部evaluates the LINQ expression in client side automatically
的工作,就像自动Tolist()
一样,而不是使用IEnumerator来保持打开状态。
为避免这种情况,我将在下面对所有将来和当前的代码进行处理。 这样就没关系了,还请确保不要在IEnumerator语句上执行,该语句会重新执行整个语句。
这还有一个额外的好处,您可以在循环之前调试列表。
在有人说这会消耗更多的内存之前,请先给我看一个测试,显示... 这不使用yield,而且编译器可能足够聪明,可以对不需要的内容进行优化。
他们说IEnumerator问题更好,但相同。
Entity Framework upgrade to 6.2.0 from 6.1.x breaks certain queries unless I enable MARS
List<Claim> claims = new List<Claim>();
var userRoles = await _userManager.GetRolesAsync(user);
//you could change this to use async and await
//var roles = await _roleManager.Roles.Where(a => userRoles.Contains(a.Name)).ToListAsync();
var roles = _roleManager.Roles.Where(a => userRoles.Contains(a.Name)).ToList();
foreach (var role in roles)
{
claims.AddRange(await _roleManager.GetClaimsAsync(role));
}
return claims;