C# 我应该在foreach C中调用ToList()吗

C# 我应该在foreach C中调用ToList()吗,c#,entity-framework,lazy-loading,C#,Entity Framework,Lazy Loading,这个代码正常吗 我应该打电话给托利斯特吗。如果是,为什么 它是一个实体框架。或者这不要紧,我可能不会打电话给名单 var followers = from user in project.Followers where followersIds.Contains(user.Id) select user; foreach (var follower in followers.ToList()) { project.Fol

这个代码正常吗

我应该打电话给托利斯特吗。如果是,为什么

它是一个实体框架。或者这不要紧,我可能不会打电话给名单

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存在的原因。

ToList存在是为了避免在迭代运行时错误时遇到修改过的集合。ToList创建集合的一个即时副本,然后您对其进行迭代,从原始源project.Followers中删除项


它看起来有点粗糙,但这就是ToList存在的原因。

好吧,假设您使用的是来自标记的实体框架。 当执行Linq表达式时,会得到一个IQueryable集合。这个IQueryable不是一个存储在内存中的truthy集合,它包含了从数据库中获取的所有记录,它是一种向数据库服务器查询的语句。我的意思是,你不会查询数据库,因为这个IQueryable是被访问的

可以通过迭代或集合转换(如IList、Array等)访问IQueryable集合

上面的块的性能稍好一些

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添加操作,而无需内存或性能开销

followers = followers.Where(/* Any Func<Type, bool> action here*/);
followers = followers.OrderBy(/* Property KeySelector... */);
如果在第一步调用ToList方法

IList followers = project.Followers.ToList();

下一个Linq表达式将被执行到内存集合中。

好吧,假设您使用的是来自标记的实体框架。 当执行Linq表达式时,会得到一个IQueryable集合。这个IQueryable不是一个存储在内存中的truthy集合,它包含了从数据库中获取的所有记录,它是一种向数据库服务器查询的语句。我的意思是,你不会查询数据库,因为这个IQueryable是被访问的

可以通过迭代或集合转换(如IList、Array等)访问IQueryable集合

上面的块的性能稍好一些

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添加操作,而无需内存或性能开销

followers = followers.Where(/* Any Func<Type, bool> action here*/);
followers = followers.OrderBy(/* Property KeySelector... */);
如果在第一步调用ToList方法

IList followers = project.Followers.ToList();

下一个Linq表达式将被执行到内存中的集合。

您可以修改foreach主体内的基础集合。@JeppeStigNielsen,这取决于很多事情;可以,但一旦执行开始,查询也可以是独立的,特别是对于IQueryable;它将是特定于实现的,但这是一个明确的风险,无论何时您从foreach中的集合中移除元素,您都应该调用该集合上的ToList。即使原始收藏是一个列表。“这是一个避免遇到无效操作异常的流行解决方法。”MarcGravel我同意。我谨慎地没有断定.ToList是否必要,因为我不知道它将如何在实体框架中实现。请注意,如果有很多追随者,这将生成大量SQL语句。您可能对修改foreach主体内的基础集合感兴趣。@JeppeStigNielsen,这取决于很多事情;可以,但一旦执行开始,查询也可以是独立的,特别是对于IQueryable;它将是特定于实现的,但这是一个明确的风险,无论何时您从foreach中的集合中移除元素,您都应该调用该集合上的ToList。即使原始收藏是一个列表。“这是一个避免遇到无效操作异常的流行解决方法。”MarcGravel我同意。我谨慎地没有断定.ToList是否必要,因为我不知道它将如何在实体框架中实现。请注意,如果有很多追随者,这将生成大量SQL语句。您可能会感兴趣的是,这是否是Linq to Objects,并且底层源(例如)是内存中的字典。ToList是必要的,因为字典生成一个IEnumerator,它将跟踪字典是否在枚举器的生存期内被修改,并在这种情况下引发异常。然而,这个Linq是一个实体框架。你知道他们的实施也会导致这种情况吗
选择修改运行时错误?@JeppeStigNielsen不,事实上我没有,所以这是一个很好的观点。它之所以存在,显然是因为编写代码的人认为需要它来避免所描述的问题。我不能说这个信念是不是真的。我将更新答案。如果这是Linq to Objects,并且底层源(比如)是内存中的字典,那么.ToList将是必需的,因为字典生成一个IEnumerator,它将跟踪字典是否在枚举器的生存期内被修改,并在这种情况下引发异常。然而,这个Linq是一个实体框架。你知道他们的实现也会导致集合修改运行时错误吗?@JeppeStigNielsen不,事实上我不知道,所以这是一个很好的观点。它之所以存在,显然是因为编写代码的人认为需要它来避免所描述的问题。我不能说这个信念是不是真的。我会更新答案。听起来都正确。但是,如果删除.ToList,我们可以从问题中回答示例中发生的情况吗?实体框架。你是对的,我没有抓住问题的重点。那么,我要补充的是,调用iterable集合的ToList是避免运行时异常的必要条件,当谈到实体框架加上Linq时,应该先执行查询,然后从已经构建的IList调用ToList。我不是本地人。所以,对我来说,它在以下方面的表现没有什么不同:1。创建Ilist变量并放入循环2中。直接在循环中调用ToList。对吗?听起来都对。但是,如果删除.ToList,我们可以从问题中回答示例中发生的情况吗?实体框架。你是对的,我没有抓住问题的重点。那么,我要补充的是,调用iterable集合的ToList是避免运行时异常的必要条件,当谈到实体框架加上Linq时,应该先执行查询,然后从已经构建的IList调用ToList。我不是本地人。所以,对我来说,它在以下方面的表现没有什么不同:1。创建Ilist变量并放入循环2中。直接在循环中调用ToList。正当