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