Error: the collection has been changed; enumeration operation may fail

I am getting this exception in the field. I don't understand how the collection can be changed during iteration. I copy everything to local variables at the beginning of the method.

  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);
        }

      

Stack trace

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 

      

+3


source to share


2 answers


Judging from the stack trace, it doesn't break inside yours foreach

(or enumerate tempEntities

, which is a simple list), but inside one of the calls ToList

, when the Select

list in the iterator list checks its state before moving to the next element.

This line in your stack trace makes me believe this:

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 loop through Select

. This makes me think that either attachedEntities

, or entitiesToDelete

change when you do 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 might be a concurrency issue.

By the way, you don't really need it Select (item => item)

, it will just be an identification projection.

+2


source


Replace this:

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

      

FROM



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

      

I got this problem when I was trying to delete while doing a loop; he was trying to change the list of items. Therefore, looping back fixed it for me.

+3


source







All Articles