我有这样的代码:
它必须使用Where
必须向db询问有关确定真/假的权限
public List<User> getUsersWhoCanDoSomething()
{
return _context
.Users
.Where(x => CanPerformAction(user))
.Take(10000)
.OrderByDescending(x => x.CreationDate)
.ToList();
}
private bool CanPerformAction(User user)
{
var permission = _context
.Permissions
.FirstOrDefault(x => x.Name == user.Permissions.Name)
.Level;
return permission > 5;
}
如何更改此代码以防止出现此异常:
A second operation started on this context before a previous operation completed.
答案 0 :(得分:1)
解决方案:
将Where
/ Filter
从LINQ链中移出
public List<User> getUsersWhoCan...()
{
var users = _context
.Users
.Include(x => x.Permissions)
.Take(10000)
.OrderByDescending(x => x.CreationDate)
.ToList();
var tempList = new List<User>();
foreach (var user in users)
{
if (CanPerformAction(user))
{
tempList.Add(user);
}
}
return tempList;
}
答案 1 :(得分:0)
问题的根源在于,一次只能对一个查询使用DbContext
对象。但是CanPerformAction
在FirstOrDefault
执行期间正在执行自己的数据库调用(由于getUsersWhoCanDoSomething
)。这就是为什么您要获得例外。
您的答案将起作用,但是您要获取的数据超出了您的期望,然后丢弃了一些数据。如果您的用户数超过10,000,则可能会因此而丢失一些用户(由于Take(10000)
)。
这应该做相同的事情(我想-我不知道您的确切数据库架构)。它将条件组合到查询中,因此您仅获得所需的数据。
return _context
.Users
.Where(u => u.Permissions.Any(l => l.Level > 5))
.Take(10000)
.OrderByDescending(x => x.CreationDate)
.ToList();
做同样事情的另一种方法是仍然使用单独的方法(从技术上来说,=>
之后的任何东西都是单独的方法),但是不要引用_context
或FirstOrDefault
(这会触发一个单独的数据库调用)。如果您使用.Where(x => CanPerformAction(user))
,这将与我上面的代码完全相同。
private bool CanPerformAction(User user)
{
return user.Permissions.Any(l => l.Level > 5);
}