diff --git a/src/MongoDB.Driver/FilteredMongoCollectionBase.cs b/src/MongoDB.Driver/FilteredMongoCollectionBase.cs index 65d95d2f7b5..17a7a3e1901 100644 --- a/src/MongoDB.Driver/FilteredMongoCollectionBase.cs +++ b/src/MongoDB.Driver/FilteredMongoCollectionBase.cs @@ -304,22 +304,22 @@ public override Task> DistinctManyAsync(IClientSessio public override TProjection FindOneAndUpdate(FilterDefinition filter, UpdateDefinition update, FindOneAndUpdateOptions options = null, CancellationToken cancellationToken = default(CancellationToken)) { - return _wrappedCollection.FindOneAndUpdate(CombineFilters(filter), update, options, cancellationToken); + return _wrappedCollection.FindOneAndUpdate(CombineFilters(filter), AdjustUpdateDefinition(update, options.IsUpsert), options, cancellationToken); } public override TProjection FindOneAndUpdate(IClientSessionHandle session, FilterDefinition filter, UpdateDefinition update, FindOneAndUpdateOptions options = null, CancellationToken cancellationToken = default(CancellationToken)) { - return _wrappedCollection.FindOneAndUpdate(session, CombineFilters(filter), update, options, cancellationToken); + return _wrappedCollection.FindOneAndUpdate(session, CombineFilters(filter), AdjustUpdateDefinition(update, options.IsUpsert), options, cancellationToken); } public override Task FindOneAndUpdateAsync(FilterDefinition filter, UpdateDefinition update, FindOneAndUpdateOptions options = null, CancellationToken cancellationToken = default(CancellationToken)) { - return _wrappedCollection.FindOneAndUpdateAsync(CombineFilters(filter), update, options, cancellationToken); + return _wrappedCollection.FindOneAndUpdateAsync(CombineFilters(filter), AdjustUpdateDefinition(update, options.IsUpsert), options, cancellationToken); } public override Task FindOneAndUpdateAsync(IClientSessionHandle session, FilterDefinition filter, UpdateDefinition update, FindOneAndUpdateOptions options = null, CancellationToken cancellationToken = default(CancellationToken)) { - return _wrappedCollection.FindOneAndUpdateAsync(session, CombineFilters(filter), update, options, cancellationToken); + return _wrappedCollection.FindOneAndUpdateAsync(session, CombineFilters(filter), AdjustUpdateDefinition(update, options.IsUpsert), options, cancellationToken); } [Obsolete("Use Aggregation pipeline instead.")] diff --git a/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5587Tests.cs b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5587Tests.cs new file mode 100644 index 00000000000..c3b3672ce41 --- /dev/null +++ b/tests/MongoDB.Driver.Tests/Linq/Linq3Implementation/Jira/CSharp5587Tests.cs @@ -0,0 +1,118 @@ +/* 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.Linq; +using MongoDB.Driver.TestHelpers; +using FluentAssertions; +using MongoDB.Bson.Serialization.Attributes; +using MongoDB.Bson.Serialization.Serializers; +using MongoDB.Driver.Linq; +using Xunit; + +namespace MongoDB.Driver.Tests.Linq.Linq3Implementation.Jira; + +public class CSharp5587Tests : LinqIntegrationTest +{ + public CSharp5587Tests(ClassFixture fixture) + : base(fixture) + { + } + + [Fact] + public void FindOneAndUpdate_should_use_correct_discriminator() + { + var collection = Fixture.Collection; + + var lion1 = new Lion { Id = 1, Name = "Lion1" }; + var updateDefinition1 = Builders.Update + .SetOnInsert(l => l.Id, 1) + .Set(l => l.Name, lion1.Name); + collection.OfType().FindOneAndUpdate( + f => f.Name == lion1.Name, + updateDefinition1, + new FindOneAndUpdateOptions { IsUpsert = true }); + + var result = collection.AsQueryable().As(BsonDocumentSerializer.Instance).Single(); + result.Should().Be( + """ + { + _id : 1, + Name : "Lion1", + _t : ["Animal", "Cat", "Lion"] + } + """); + } + + [Fact] + public void UpdateOne_should_use_correct_discriminator() + { + var collection = Fixture.Collection; + + var lion2 = new Lion { Id = 2, Name = "Lion2" }; + var updateDefinition2 = Builders.Update + .SetOnInsert(l => l.Id, lion2.Id) + .Set(l => l.Name, lion2.Name); + collection.OfType().UpdateOne( + f => f.Name == lion2.Name, + updateDefinition2, + new UpdateOptions { IsUpsert = true }); + + var result = collection.AsQueryable().As(BsonDocumentSerializer.Instance).Single(); + result.Should().Be( + """ + { + _id : 2, + Name : "Lion2", + _t : ["Animal", "Cat", "Lion"] + } + """); + } + + [BsonDiscriminator(RootClass = true)] + [BsonKnownTypes(typeof(Cat), typeof(Dog))] + public class Animal + { + public int Id { get; set; } + } + + [BsonKnownTypes(typeof(Lion), typeof(Tiger))] + public class Cat : Animal + { + } + + public class Dog : Animal + { + } + + public class Lion : Cat + { + public string Name { get; set; } + } + public class Tiger : Cat + { + } + + public sealed class ClassFixture : MongoCollectionFixture + { + public override bool InitializeDataBeforeEachTestCase => true; + + protected override IEnumerable InitialData => null; + // [ + // new Animal { } + // ]; + } +}