首页 > 解决方案 > 访问新保存对象上的 ID 时 MongoDB C# 驱动程序 InvalidOperationException

问题描述

我正在使用 C# 驱动程序 V2.9.3 在 MongoDB 中保存一个项目。

我看到偶尔会抛出以下异常(尽管一旦它发生一次,它似乎更容易再次发生)。

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

请参阅下面的我的编辑代码

            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
            }

以及对象定义的相关部分

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

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

感谢您提供任何帮助,我们仅在使用 mongodb atlas M10 实例作为服务器的生产中观察到这种情况。

标签: c#mongodb

解决方案


您可以使用 ObjectId 作为文档的唯一标识符。

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
}

对象模型将是,

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

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

推荐阅读