这段代码正常吗?
我应该调用ToList((吗。如果是,为什么?
它是一个实体框架。或者这没关系,我可能不会打电话列出?
var followers = from user in project.Followers
where followersIds.Contains(user.Id)
select user;
foreach (var follower in followers.ToList())
{
project.Followers.Remove(follower);
}
ToList
是为了避免在迭代运行时错误时遇到修改过的集合。ToList()
生成集合的热切副本,然后对其进行迭代,从原始源project.Followers
中删除项。
它看起来有点古怪,但这就是ToList
出现的原因。
假设您使用的是实体框架(来自标记(
执行Linq
表达式时,会得到一个IQueryable
集合。这个IQueryable
并不是一个存储在内存中的真实集合,所有记录都是从数据库中提取的,它有点像是一个向数据库服务器查询的语句。我的意思是,你不会查询数据库,因为这个IQueryable
被访问了
IQueryable
集合可以通过迭代或集合强制转换(如IList
、Array
…(来访问
/// This will yield item by item trough the loop.
IQueryable followers = /* linq expression */
foreach (var follower in followers)
{
// ...
}
上面的区块性能稍好。
IQueryable followers = /* linq expression */
IList list = followers.ToList(); // At this point, the query is executed in the database server
foreach (var follower in list)
{
// ...
}
虽然这种说法更安全
通常的做法是将IQueryable
转换为IList
或类似的类型,以防止并发问题、线程问题等。
重要的是,一旦查询上的所有操作(过滤、排序…(完成,就要"查找"IQueryable
拥有类似的IQueryable
IQueryable followers = project.Followers;
您现在可以向IQueryable
添加操作,而不需要内存或性能成本。
followers = followers.Where(/* Any Func<Type, bool> action here*/);
followers = followers.OrderBy(/* Property KeySelector... */);
一旦构建了所有查询,就可以执行该查询。
IList realDataInMemory = followers.ToList();
如果在第一步调用#ToList
方法。
IList followers = project.Followers.ToList();
下一个CCD_ 18表达式将被执行到内存中的集合。