【问题标题】:MongoDB C# driver InvalidOperationException when accessing ID on newly saved object访问新保存对象上的 ID 时 MongoDB C# 驱动程序 InvalidOperationException
【发布时间】:2020-04-08 21:03:09
【问题描述】:

我正在使用 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


【解决方案1】:

您可以使用 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
  }

【讨论】:

  • _id 字段可以是任何类型,即使它通常是 objectId 参见此处例如 stackoverflow.com/a/6069830/1658329。鉴于这段代码在 99% 的时间里都能正常工作,我认为这不是问题。
  • 请务必提供您正在处理的循环,该循环调用插入文档。
【解决方案2】:

原来的问题是我有一个任务因引用我正在保存的对象而超时,它恰好在将项目保存在 Mogo 中的同时完成并将项目添加到字典属性.

【讨论】:

    猜你喜欢
    • 2013-09-01
    • 2011-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-20
    • 1970-01-01
    相关资源
    最近更新 更多