After upgrading to 2.19.0 (due to the security vulnerability) we found that our integration tests fail trying to call UpdateManyAsync with the following exception:
Error Message: MongoDB.Driver.Linq.ExpressionNotSupportedException : Expression not supported: Convert(Convert(x, IRankedObj).Rank, Nullable`1). Stack Trace: at MongoDB.Driver.Linq.Linq3Implementation.Translators.ExpressionToFilterTranslators.ToFilterFieldTranslators.ConvertExpressionToFilterFieldTranslator.Translate(TranslationContext context, UnaryExpression expression) at MongoDB.Driver.Linq.Linq3Implementation.LinqProviderAdapterV3.TranslateExpressionToField[TDocument,TField](Expression`1 expression, IBsonSerializer`1 documentSerializer, IBsonSerializerRegistry serializerRegistry, Boolean allowScalarValueForArrayField) at MongoDB.Driver.ExpressionFieldDefinition`2.Render(IBsonSerializer`1 documentSerializer, IBsonSerializerRegistry serializerRegistry, LinqProvider linqProvider, Boolean allowScalarValueForArrayField) at MongoDB.Driver.ExpressionFieldDefinition`2.Render(IBsonSerializer`1 documentSerializer, IBsonSerializerRegistry serializerRegistry, LinqProvider linqProvider) at MongoDB.Driver.OperatorUpdateDefinition`2.Render(IBsonSerializer`1 documentSerializer, IBsonSerializerRegistry serializerRegistry, LinqProvider linqProvider) at MongoDB.Driver.MongoCollectionImpl`1.ConvertWriteModelToWriteRequest(WriteModel`1 model, Int32 index) at System.Linq.Enumerable.SelectIterator[TSource,TResult](IEnumerable`1 source, Func`3 selector)+MoveNext() at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source) at MongoDB.Driver.Core.Operations.BulkMixedWriteOperation..ctor(CollectionNamespace collectionNamespace, IEnumerable`1 requests, MessageEncoderSettings messageEncoderSettings) at MongoDB.Driver.MongoCollectionImpl`1.CreateBulkWriteOperation(IClientSessionHandle session, IEnumerable`1 requests, BulkWriteOptions options) at MongoDB.Driver.MongoCollectionImpl`1.BulkWriteAsync(IClientSessionHandle session, IEnumerable`1 requests, BulkWriteOptions options, CancellationToken cancellationToken) at MongoDB.Driver.MongoCollectionBase`1.UpdateManyAsync(FilterDefinition`1 filter, UpdateDefinition`1 update, UpdateOptions options, Func`3 bulkWriteAsync) at ApiServer.Services.MongoDbService.<>c__DisplayClass37_0`1.<<DeleteRankObjFromId>b__0>d.MoveNext() in /builds/hydra/hydra-src/apps/API-Server/ApiServer/Services/MongoDbService.cs:line 470 --- End of stack trace from previous location --- at ApiServer.Services.MongoDbService.<>c__DisplayClass30_0.<<WriteInTransaction>b__0>d.MoveNext() in /builds/hydra/hydra-src/apps/API-Server/ApiServer/Services/MongoDbService.cs:line 325 --- End of stack trace from previous location --- at MongoDB.Driver.TransactionExecutor.ExecuteCallbackAsync[TResult](IClientSessionHandle clientSession, Func`3 callbackAsync, DateTime startTime, IClock clock, CancellationToken cancellationToken) at MongoDB.Driver.TransactionExecutor.ExecuteCallbackAsync[TResult](IClientSessionHandle clientSession, Func`3 callbackAsync, DateTime startTime, IClock clock, CancellationToken cancellationToken) at MongoDB.Driver.TransactionExecutor.ExecuteWithRetriesAsync[TResult](IClientSessionHandle clientSession, Func`3 callbackAsync, TransactionOptions transactionOptions, IClock clock, CancellationToken cancellationToken) at ApiServer.Services.MongoDbService.WriteInTransaction(Func`2 action) in /builds/hydra/hydra-src/apps/API-Server/ApiServer/Services/MongoDbService.cs:line 321 at ApiServer.Services.MongoDbService.DeleteRankObjFromId[T](ObjectId id, String collectionName) in /builds/hydra/hydra-src/apps/API-Server/ApiServer/Services/MongoDbService.cs:line 459 at IntegrationTests.PabxMappingTests.DeletePabxMapping_Deleted() in /builds/hydra/hydra-src/apps/API-Server/IntegrationTests/PabxMappingTests.cs:line 181 at NUnit.Framework.Internal.TaskAwaitAdapter.GenericAdapter`1.BlockUntilCompleted() at NUnit.Framework.Internal.MessagePumpStrategy.NoMessagePumpStrategy.WaitForCompletion(AwaitAdapter awaiter) at NUnit.Framework.Internal.AsyncToSyncAdapter.Await(Func`1 invoke) at NUnit.Framework.Internal.Commands.TestMethodCommand.RunTestMethod(TestExecutionContext context) at NUnit.Framework.Internal.Commands.TestMethodCommand.Execute(TestExecutionContext context) at NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.<>c__DisplayClass1_0.<Execute>b__0() at NUnit.Framework.Internal.Commands.DelegatingTestCommand.RunTestMethodInThreadAbortSafeZone(TestExecutionContext context, Action action) Standard Output Messages: 2023-03-05T23:27:14.4711824+00:00 [MongoDbService] [Error] Failed to delete Ranked object from collection pabx_map 2023-03-05T23:27:18.0832340+00:00 [ApiCacheUpdaterService] [Information] Initial sync complete 2023-03-05T23:27:18.0833334+00:00 [MongoDbService] [Information] Begin watch from ts=7207207825678794752, tid=97 2023-03-05T23:27:18.0896708+00:00 [MongoDbService] [Debug] Watch cancelled
This is the method that calls UpdateManyAsync:
public async Task DeleteRankObjFromId<T>(ObjectId id, string collectionName) where T : IStoredRankedObj { await WriteInTransaction(async session => { try { var collection = _mongoDatabase.GetCollection<T>(collectionName); var cursor = await collection.FindAsync(session, rankObj => rankObj.Id == id); var objectToDelete = await cursor.FirstOrDefaultAsync(); // need rank of object to be deleted to adjust others if (objectToDelete != null) { var result = await collection.DeleteOneAsync(session, rankObj => rankObj.Id == id); var updateDefinition = Builders<T>.Update.Inc(x => (int?)x.Rank, -1); await collection.UpdateManyAsync( session, existingRankObj => existingRankObj.Rank > objectToDelete.Rank, updateDefinition); } } catch (Exception exception) { _logger.LogError(exception, "Failed to delete Ranked object from collection {CollectionName}", collectionName); throw; } }); }
The type T is StorePabxMapping class defined as follows:
public record StoredPabxMapping : PabxMapping, IStoredRankedObj { public StoredPabxMapping() { } public StoredPabxMapping(PabxMapping pabxMap) { Rank = pabxMap.Rank; Replace = pabxMap.Replace; Match = pabxMap.Match; } public ObjectId Id { get; set; } } public record PabxMapping : IRankedObj { public uint? Rank { get; set; } [Required] [RegularExpression(@"^(\d+|\d*\*)$", ErrorMessage = "'InternalNumber' formatted incorrectly")] public string Match { get; set; } = ""; [Required] [RegularExpression(@"^(\+?\d+|\+?\d*\*)$", ErrorMessage = "'PhoneNumber' formatted incorrectly")] public string Replace { get; set; } = ""; } public interface IRankedObj { uint? Rank { get; set; } } public interface IStoredRankedObj : IRankedObj { ObjectId Id { get; set; } }