0

I'm saving an item in MongoDB using the C# driver V2.9.3.

I'm seeing the following exception being thrown occasionally (although once its happened once it appears to be more lightly to happen again).

System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
  at System.Collections.Generic.Dictionary`2.Enumerator.MoveNext()
  at MongoDB.Bson.Serialization.Serializers.DictionarySerializerBase`3.SerializeDocumentRepresentation(BsonSerializationContext context, TDictionary value)
  at MongoDB.Bson.Serialization.Serializers.ClassSerializerBase`1.Serialize(BsonSerializationContext context, BsonSerializationArgs args, TValue value)
  at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Serialize(IBsonSerializer serializer, BsonSerializationContext context, Object value)
  at MongoDB.Bson.Serialization.BsonClassMapSerializer`1.SerializeClass(BsonSerializationContext context, BsonSerializationArgs args, TClass document)
  at MongoDB.Bson.Serialization.BsonClassMapSerializer`1.Serialize(BsonSerializationContext context, BsonSerializationArgs args, TClass value)
  at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Serialize(IBsonSerializer serializer, BsonSerializationContext context, Object value)
  at MongoDB.Bson.Serialization.Serializers.BsonValueSerializerBase`1.Serialize(BsonSerializationContext context, BsonSerializationArgs args, TBsonValue value)
  at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Serialize(IBsonSerializer serializer, BsonSerializationContext context, Object value)
  at MongoDB.Bson.Serialization.Serializers.BsonValueSerializerBase`1.Serialize(BsonSerializationContext context, BsonSerializationArgs args, TBsonValue value)
  at MongoDB.Driver.Core.WireProtocol.Messages.Encoders.BinaryEncoders.CommandMessageBinaryEncoder.WriteType1Section(BsonBinaryWriter writer, Type1CommandMessageSection section, Int64 messageStartPosition)
  at MongoDB.Driver.Core.WireProtocol.Messages.Encoders.BinaryEncoders.CommandMessageBinaryEncoder.WriteSections(BsonBinaryWriter writer, IEnumerable`1 sections, Int64 messageStartPosition)
  at MongoDB.Driver.Core.WireProtocol.Messages.Encoders.BinaryEncoders.CommandMessageBinaryEncoder.WriteMessage(CommandMessage message)
  at MongoDB.Driver.Core.Connections.BinaryConnection.SendMessagesHelper.EncodeMessages(CancellationToken cancellationToken, List`1& sentMessages)
  at MongoDB.Driver.Core.Connections.BinaryConnection.SendMessagesAsync(IEnumerable`1 messages, MessageEncoderSettings messageEncoderSettings, CancellationToken cancellationToken)
  at MongoDB.Driver.Core.WireProtocol.CommandUsingCommandMessageWireProtocol`1.ExecuteAsync(IConnection connection, CancellationToken cancellationToken)
  at MongoDB.Driver.Core.Servers.Server.ServerChannel.ExecuteProtocolAsync[TResult](IWireProtocol`1 protocol, CancellationToken cancellationToken)
  at MongoDB.Driver.Core.Operations.RetryableWriteOperationExecutor.ExecuteAsync[TResult](IRetryableWriteOperation`1 operation, RetryableWriteContext context, CancellationToken cancellationToken)
  at MongoDB.Driver.Core.Operations.BulkUnmixedWriteOperationBase`1.ExecuteBatchAsync(RetryableWriteContext context, Batch batch, CancellationToken cancellationToken)
  at MongoDB.Driver.Core.Operations.BulkUnmixedWriteOperationBase`1.ExecuteBatchesAsync(RetryableWriteContext context, CancellationToken cancellationToken)
  at MongoDB.Driver.Core.Operations.BulkMixedWriteOperation.ExecuteBatchAsync(RetryableWriteContext context, Batch batch, CancellationToken cancellationToken)
  at MongoDB.Driver.Core.Operations.BulkMixedWriteOperation.ExecuteAsync(IWriteBinding binding, CancellationToken cancellationToken)
  at MongoDB.Driver.OperationExecutor.ExecuteWriteOperationAsync[TResult](IWriteBinding binding, IWriteOperation`1 operation, CancellationToken cancellationToken)
  at MongoDB.Driver.MongoCollectionImpl`1.ExecuteWriteOperationAsync[TResult](IClientSessionHandle session, IWriteOperation`1 operation, CancellationToken cancellationToken)
  at MongoDB.Driver.MongoCollectionImpl`1.BulkWriteAsync(IClientSessionHandle session, IEnumerable`1 requests, BulkWriteOptions options, CancellationToken cancellationToken)
  at MongoDB.Driver.MongoCollectionImpl`1.UsingImplicitSessionAsync[TResult](Func`2 funcAsync, CancellationToken cancellationToken)
  at MongoDB.Driver.MongoCollectionBase`1.InsertOneAsync(TDocument document, InsertOneOptions options, Func`3 bulkWriteAsync)
  at MyApp.Program.MongoDbResultSaver.Save(PhishingResult result, IEmailHolder email) line 107
  at MyApp.Program.Services.MongoDbResultSaver.Save(PhishingResult result, IEmailHolder email) line 121

See below for my redacted code

            try
            {
                var obj= new MyDbObject()
                {
                    ID = Guid.NewGuid().ToString(),
            // meny propertys including objects, and lists of objects

                };

                var metaCollection = db.GetCollection<MyDbObject>("MyDbObject");

                await metaCollection.InsertOneAsync(obj);
                _logger.Info("Saved with ID " + obj.ID);//line 107 in stack trace where the error is coming from
            }
            catch (Exception e)
            {
                _logger.Error($"Failed to save metastore with error {e}");
                throw;//line 121 in stacktrace where the error is being rethrown
            }

And relevant part of object definition

  [BsonIgnoreExtraElements]
  public class MyDbObject
  {
    [BsonId]
    public string ID { get; set; }

    [BsonElement("etc")]
//etc
  }

Any help is appreciated, we have only observed this happening in production with mongodb atlas M10 instance as the server.

Tom Hazell
  • 15
  • 1
  • 1
  • 8
  • This is going to be the tricky part.. can you reproduce it? If not, how can any of the solutions being provided will help you ? – Jawad Dec 18 '19 at 22:07
  • Does this answer your question? [Collection was modified; enumeration operation may not execute](https://stackoverflow.com/questions/604831/collection-was-modified-enumeration-operation-may-not-execute) – Jawad Dec 18 '19 at 22:17

2 Answers2

0

You can use ObjectId for unique identifier of document.

try
{
    var obj= new MyDbObject()
    {
        ID = ObjectId.GenerateNewId(),
        // many properties including objects, and lists of objects

    };

    var metaCollection = db.GetCollection<MyDbObject>("MyDbObject");

    await metaCollection.InsertOneAsync(obj);
    _logger.Info("Saved with ID " + obj.ID);//line 107 in stack trace where the error is coming from
}
catch (Exception e)
{
    _logger.Error($"Failed to save metastore with error {e}");
    throw;//line 121 in stacktrace where the error is being rethrown
}

Object model will be,

[BsonIgnoreExtraElements]
public class MyDbObject
{
    [BsonId]
    public ObjectId ID { get; set; }

    [BsonElement("etc")]
//etc
  }
Murat Acarsoy
  • 294
  • 3
  • 10
  • The _id field can be any type, even if it is usualy an objectId see here for example https://stackoverflow.com/a/6069830/1658329. And given that this code works 99% of this time i dont think that is the issue. – Tom Hazell Dec 16 '19 at 14:25
  • Please do provide the loop that you are going over that makes the call for inserting the document. – Jawad Dec 18 '19 at 22:13
0

Turns out the issue is that I had a task that had timed out with a reference to the object I was saving, it happened to complete and add an item to the a dictionary property at the same time the item was saving in Mogo.

Tom Hazell
  • 15
  • 1
  • 1
  • 8