[CSHARP-4560] UpdateManyAsync fails after upgrade to 2.19.0 Created: 06/Mar/23  Updated: 21/Apr/23

Status: Backlog
Project: C# Driver
Component/s: LINQ3
Affects Version/s: None
Fix Version/s: None

Type: Task Priority: Unknown
Reporter: Daniel Hughes Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: triage
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

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; }
}

 



 Comments   
Comment by Robert Stam [ 07/Mar/23 ]

Thanks for reporting this. I will investigate further before long.

Generated at Wed Feb 07 21:48:36 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.