diff --git a/src/MongoDB.Driver/BulkWriteInsertOneResult.cs b/src/MongoDB.Driver/BulkWriteInsertOneResult.cs index ca684cf9521..290b65462ed 100644 --- a/src/MongoDB.Driver/BulkWriteInsertOneResult.cs +++ b/src/MongoDB.Driver/BulkWriteInsertOneResult.cs @@ -13,6 +13,7 @@ * limitations under the License. */ +using System; using MongoDB.Bson; namespace MongoDB.Driver @@ -25,6 +26,19 @@ public class BulkWriteInsertOneResult /// /// The id of the inserted document. /// - public BsonValue InsertedId { get; init; } + [Obsolete("InsertedId is deprecated and will be removed in future versions. Use DocumentId instead.")] + public BsonValue InsertedId + { + get => BsonValue.Create(DocumentId); + init + { + DocumentId = value; + } + } + + /// + /// The id of the inserted document. + /// + public object DocumentId { get; init; } } } diff --git a/src/MongoDB.Driver/Core/Operations/ClientBulkWriteOperation.cs b/src/MongoDB.Driver/Core/Operations/ClientBulkWriteOperation.cs index b994a95388d..2c913598c00 100644 --- a/src/MongoDB.Driver/Core/Operations/ClientBulkWriteOperation.cs +++ b/src/MongoDB.Driver/Core/Operations/ClientBulkWriteOperation.cs @@ -33,7 +33,7 @@ internal sealed class ClientBulkWriteOperation : RetryableWriteCommandOperationB { private readonly bool? _bypassDocumentValidation; private readonly bool _errorsOnly; - private readonly Dictionary _idsMap = new(); + private readonly Dictionary _idsMap = new(); private readonly BsonDocument _let; private readonly RenderArgs _renderArgs; private readonly IBatchableSource _writeModels; @@ -331,7 +331,7 @@ private void PopulateIndividualResponses(IEnumerable individualRes _idsMap.TryGetValue(operationIndex, out var insertedId); bulkWriteResult.InsertResults.Add(operationIndex, new() { - InsertedId = insertedId + DocumentId = insertedId }); } else if (writeModelType == typeof(BulkWriteUpdateOneModel<>) || writeModelType == typeof(BulkWriteUpdateManyModel<>) || writeModelType == typeof(BulkWriteReplaceOneModel<>)) diff --git a/src/MongoDB.Driver/Core/WireProtocol/Messages/CommandMessageSection.cs b/src/MongoDB.Driver/Core/WireProtocol/Messages/CommandMessageSection.cs index 0cfbf749696..384ff5425f6 100644 --- a/src/MongoDB.Driver/Core/WireProtocol/Messages/CommandMessageSection.cs +++ b/src/MongoDB.Driver/Core/WireProtocol/Messages/CommandMessageSection.cs @@ -133,7 +133,7 @@ internal sealed class ClientBulkWriteOpsCommandMessageSection : BatchableCommand { public ClientBulkWriteOpsCommandMessageSection( IBatchableSource operations, - Dictionary idsMap, + Dictionary idsMap, int? maxBatchCount, int? maxDocumentSize, RenderArgs renderArgs) @@ -144,7 +144,7 @@ public ClientBulkWriteOpsCommandMessageSection( RenderArgs = renderArgs; } - public Dictionary IdsMap { get; } + public Dictionary IdsMap { get; } public new IBatchableSource Documents { get; } public RenderArgs RenderArgs { get; } } diff --git a/src/MongoDB.Driver/Core/WireProtocol/Messages/Encoders/BinaryEncoders/ClientBulkWriteOpsSectionFormatter.cs b/src/MongoDB.Driver/Core/WireProtocol/Messages/Encoders/BinaryEncoders/ClientBulkWriteOpsSectionFormatter.cs index 8fce04fb521..353f45dab5e 100644 --- a/src/MongoDB.Driver/Core/WireProtocol/Messages/Encoders/BinaryEncoders/ClientBulkWriteOpsSectionFormatter.cs +++ b/src/MongoDB.Driver/Core/WireProtocol/Messages/Encoders/BinaryEncoders/ClientBulkWriteOpsSectionFormatter.cs @@ -32,7 +32,7 @@ internal sealed class ClientBulkWriteOpsSectionFormatter : ICommandMessageSectio private MemoryStream _nsInfoMemoryStream; private BsonBinaryWriter _nsInfoWriter; private IBsonSerializerRegistry _serializerRegistry; - private Dictionary _idsMap; + private Dictionary _idsMap; private int _currentIndex; public ClientBulkWriteOpsSectionFormatter(long? maxSize) @@ -150,7 +150,7 @@ public void RenderInsertOne(RenderArgs renderArgs, Bson WriteStartModel(serializationContext, "insert", model); var documentSerializer = _serializerRegistry.GetSerializer(); var documentId = documentSerializer.SetDocumentIdIfMissing(null, model.Document); - _idsMap[_currentIndex] = BsonValue.Create(documentId); + _idsMap[_currentIndex] = documentId; serializationContext.Writer.WriteName("document"); documentSerializer.Serialize(serializationContext, model.Document); WriteEndModel(serializationContext); diff --git a/tests/MongoDB.Driver.Tests/Jira/CSharp5697Tests.cs b/tests/MongoDB.Driver.Tests/Jira/CSharp5697Tests.cs new file mode 100644 index 00000000000..4278485b93c --- /dev/null +++ b/tests/MongoDB.Driver.Tests/Jira/CSharp5697Tests.cs @@ -0,0 +1,106 @@ +/* Copyright 2010-present MongoDB Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using FluentAssertions; +using MongoDB.Bson.Serialization; +using MongoDB.Driver.Core.Misc; +using MongoDB.Driver.TestHelpers; +using MongoDB.TestHelpers.XunitExtensions; +using Xunit; + +namespace MongoDB.Driver.Tests.Jira; + +public class CSharp5697Tests : IntegrationTest +{ + public CSharp5697Tests(ClassFixture fixture) + : base(fixture, server => server.Supports(Feature.ClientBulkWrite)) + { + } + + [Theory] + [ParameterAttributeData] + public async Task ClientBulkWrite_supports_complex_id([Values(true, false)] bool async) + { + var id = async ? "1" : "2"; + var options = new ClientBulkWriteOptions { VerboseResult = true }; + BulkWriteModel[] models = + [ + new BulkWriteInsertOneModel( + Fixture.Collection.CollectionNamespace, + new Document(new DocumentId(id))) + ]; + + var result = async ? + await Fixture.Client.BulkWriteAsync(models, options) : + Fixture.Client.BulkWrite(models, options); + + result.InsertResults[0].DocumentId.Should().BeOfType() + .Subject.Key.Should().Be(id); + } + + public class Document + { + public Document(DocumentId id) + { + Id = id; + } + + public DocumentId Id { get; } + } + + public class DocumentId + { + public DocumentId(string key) + { + Key = key; + } + + public string Key { get; } + } + + public sealed class DocumentIdSerializer : IBsonSerializer + { + public Type ValueType => typeof(DocumentId); + + public DocumentId Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + => new DocumentId(context.Reader.ReadString()); + + public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, DocumentId value) + => context.Writer.WriteString(value.Key); + + public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value) + { + var id = (DocumentId)value; + Serialize(context, args, id); + } + + object IBsonSerializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) + => Deserialize(context, args); + } + + public class ClassFixture : MongoCollectionFixture + { + public ClassFixture() + { + BsonSerializer.RegisterSerializer( new DocumentIdSerializer()); + } + + protected override IEnumerable InitialData => null; + } +} + diff --git a/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedClientBulkWriteOperation.cs b/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedClientBulkWriteOperation.cs index 10e1adab54b..f87829cc29b 100644 --- a/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedClientBulkWriteOperation.cs +++ b/tests/MongoDB.Driver.Tests/UnifiedTestOperations/UnifiedClientBulkWriteOperation.cs @@ -102,7 +102,7 @@ public static BsonDocument ConvertClientBulkWriteResult(ClientBulkWriteResult re { "deletedCount", (int)result.DeletedCount }, { "insertResults", ConvertResults(result.InsertResults, - item => new() { { "insertedId", item.InsertedId } }) + item => new() { { "insertedId", BsonValue.Create(item.DocumentId) } }) }, { "updateResults", ConvertResults(result.UpdateResults,