2

我一直在现场处理这个异常。我不明白如何在迭代时修改集合。我在方法开始时将所有内容复制到局部变量。

  public void Flush() {
            var tempEntities = attachedEntities.Select(item => item).ToList();
            attachedEntities.Clear();

            var tempEntitiesToDelete = entitiesToDelete.Select(item => item).ToList();
            entitiesToDelete.Clear();

            foreach (var attachedEntity in tempEntities) {
                var isTransient = (bool)GetPrivateField(attachedEntity.GetType(), attachedEntity, "isTransient");
                if (isTransient)
                    db.Insert(attachedEntity);
                else
                    db.Update(attachedEntity);
            }

            foreach (var entity in tempEntitiesToDelete)
                db.Delete(entity);
        }

堆栈跟踪

System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
  at System.Collections.Generic.List`1 Enumerator[Compass.Mobile.Core.DataAccess.IEntity].VerifyState () [0x00000] in <filename unknown>:0 
  at System.Collections.Generic.List`1 Enumerator[Compass.Mobile.Core.DataAccess.IEntity].MoveNext () [0x00000] in <filename unknown>:0 
  at System.Linq.Enumerable <CreateSelectIterator>c__Iterator1D`2[Compass.Mobile.Core.DataAccess.IEntity,Compass.Mobile.Core.DataAccess.IEntity].MoveNext () [0x00000] in <filename unknown>:0 
  at System.Collections.Generic.List`1[Compass.Mobile.Core.DataAccess.IEntity].AddEnumerable (IEnumerable`1 enumerable) [0x00000] in <filename unknown>:0 
  at System.Collections.Generic.List`1[Compass.Mobile.Core.DataAccess.IEntity]..ctor (IEnumerable`1 collection) [0x00000] in <filename unknown>:0 
  at System.Linq.Enumerable.ToList[TSource] (IEnumerable`1 source) [0x00000] in <filename unknown>:0 
  at Compass.Mobile.Core.DataAccess.Session.Flush () [0x00000] in <filename unknown>:0 
  at Compass.Mobile.Core.DataAccess.Session.Commit () [0x00000] in <filename unknown>:0 
  at Compass.Mobile.Core.Bootstrap.CommandBus.Flush () [0x00000] in <filename unknown>:0 
4

2 回答 2

3

替换这个:

foreach (var entity in tempEntitiesToDelete)
     db.Delete(entity);

和:

for (var i = tempEntitiesToDelete.Count - 1; i >= 0; i--)
   db.Delete(tempEntitiesToDelete[i]);

当我在循环中尝试删除时遇到了这个问题;它试图修改项目列表。因此,向后循环为我修复了它。

于 2013-02-08T19:06:40.697 回答
2

Judging by the stack trace, it's not failing inside your foreach (or enumerating tempEntities which is a plain list) but inside one of ToList calls, when Select iterator's underlying list checks its state before moving on to next item.

This line in your stack trace makes me believe so:

at System.Linq.Enumerable <CreateSelectIterator>c__Iterator1D`2[Compass.Mobile.Core.DataAccess.IEntity,Compass.Mobile.Core.DataAccess.IEntity].MoveNext () [0x00000] in <filename unknown>:0 

Your foreach loop variable is just a list, so it doesn't go through Select. This leads me to believe that either attachedEntities or entitiesToDelete change while you're doing Select over them:

/* Failing here... */
var tempEntities = attachedEntities.Select(item => item).ToList();
attachedEntities.Clear();

/* ...or here*/
var tempEntitiesToDelete = entitiesToDelete.Select(item => item).ToList();
entitiesToDelete.Clear();

/* ...but not here! */
foreach (var attachedEntity in tempEntities) {
   // ...
}

It could very well be a concurrency issue.

By the way, you really don't need Select (item => item), it would just be an identity projection.

于 2013-02-08T19:16:17.107 回答