Uploaded image for project: 'C# Driver'
  1. C# Driver
  2. CSHARP-4993

Divide Decimal in Projection throws TruncationException

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Unknown Unknown
    • 2.25.0
    • Affects Version/s: 2.24.0
    • Component/s: None
    • None
    • Fully Compatible
    • Dotnet Drivers
    • Not Needed
    • Hide

      1. What would you like to communicate to the user about this feature?
      2. Would you like the user to see examples of the syntax and/or executable code and its output?
      3. Which versions of the driver/connector does this apply to?

      Show
      1. What would you like to communicate to the user about this feature? 2. Would you like the user to see examples of the syntax and/or executable code and its output? 3. Which versions of the driver/connector does this apply to?

      Summary

      When attempting to project a calculated property of type decimal, the divide operator throws System.FormatException due to a TruncationException error.

      System.FormatException
        HResult=0x80131537
        Message=An error occurred while deserializing the GBP property of class <>f__AnonymousType0`2[[System.Decimal, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Decimal, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]: Truncation resulted in data loss.
        Source=MongoDB.Bson
        StackTrace:
         at MongoDB.Bson.Serialization.BsonClassMapSerializer`1.DeserializeMemberValue(BsonDeserializationContext context, BsonMemberMap memberMap)
         at MongoDB.Bson.Serialization.BsonClassMapSerializer`1.DeserializeClass(BsonDeserializationContext context)
         at MongoDB.Bson.Serialization.BsonClassMapSerializer`1.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
         at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Deserialize[TValue](IBsonSerializer`1 serializer, BsonDeserializationContext context)
         at MongoDB.Bson.Serialization.Serializers.EnumerableSerializerBase`2.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
         at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Deserialize[TValue](IBsonSerializer`1 serializer, BsonDeserializationContext context)
         at MongoDB.Driver.Core.Operations.AggregateOperation`1.CursorDeserializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
         at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Deserialize[TValue](IBsonSerializer`1 serializer, BsonDeserializationContext context)
         at MongoDB.Driver.Core.Operations.AggregateOperation`1.AggregateResultDeserializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
         at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Deserialize[TValue](IBsonSerializer`1 serializer, BsonDeserializationContext context)
         at MongoDB.Driver.Core.WireProtocol.CommandUsingCommandMessageWireProtocol`1.ProcessResponse(ConnectionId connectionId, CommandMessage responseMessage)
         at MongoDB.Driver.Core.WireProtocol.CommandUsingCommandMessageWireProtocol`1.Execute(IConnection connection, CancellationToken cancellationToken)
         at MongoDB.Driver.Core.WireProtocol.CommandWireProtocol`1.Execute(IConnection connection, CancellationToken cancellationToken)
         at MongoDB.Driver.Core.Servers.Server.ServerChannel.ExecuteProtocol[TResult](IWireProtocol`1 protocol, ICoreSession session, CancellationToken cancellationToken)
         at MongoDB.Driver.Core.Servers.Server.ServerChannel.Command[TResult](ICoreSession session, ReadPreference readPreference, DatabaseNamespace databaseNamespace, BsonDocument command, IEnumerable`1 commandPayloads, IElementNameValidator commandValidator, BsonDocument additionalOptions, Action`1 postWriteAction, CommandResponseHandling responseHandling, IBsonSerializer`1 resultSerializer, MessageEncoderSettings messageEncoderSettings, CancellationToken cancellationToken)
         at MongoDB.Driver.Core.Operations.CommandOperationBase`1.ExecuteProtocol(IChannelHandle channel, ICoreSessionHandle session, ReadPreference readPreference, CancellationToken cancellationToken)
         at MongoDB.Driver.Core.Operations.ReadCommandOperation`1.ExecuteAttempt(RetryableReadContext context, Int32 attempt, Nullable`1 transactionNumber, CancellationToken cancellationToken)
         at MongoDB.Driver.Core.Operations.RetryableReadOperationExecutor.Execute[TResult](IRetryableReadOperation`1 operation, RetryableReadContext context, CancellationToken cancellationToken)
         at MongoDB.Driver.Core.Operations.ReadCommandOperation`1.Execute(RetryableReadContext context, CancellationToken cancellationToken)
         at MongoDB.Driver.Core.Operations.AggregateOperation`1.Execute(RetryableReadContext context, CancellationToken cancellationToken)
         at MongoDB.Driver.Core.Operations.AggregateOperation`1.Execute(IReadBinding binding, CancellationToken cancellationToken)
         at MongoDB.Driver.OperationExecutor.ExecuteReadOperation[TResult](IReadBinding binding, IReadOperation`1 operation, CancellationToken cancellationToken)
         at MongoDB.Driver.MongoCollectionImpl`1.ExecuteReadOperation[TResult](IClientSessionHandle session, IReadOperation`1 operation, ReadPreference readPreference, CancellationToken cancellationToken)
         at MongoDB.Driver.MongoCollectionImpl`1.ExecuteReadOperation[TResult](IClientSessionHandle session, IReadOperation`1 operation, CancellationToken cancellationToken)
         at MongoDB.Driver.MongoCollectionImpl`1.Aggregate[TResult](IClientSessionHandle session, PipelineDefinition`2 pipeline, AggregateOptions options, CancellationToken cancellationToken)
         at MongoDB.Driver.MongoCollectionImpl`1.<>c__DisplayClass22_0`1.<Aggregate>b__0(IClientSessionHandle session)
         at MongoDB.Driver.MongoCollectionImpl`1.UsingImplicitSession[TResult](Func`2 func, CancellationToken cancellationToken)
         at MongoDB.Driver.MongoCollectionImpl`1.Aggregate[TResult](PipelineDefinition`2 pipeline, AggregateOptions options, CancellationToken cancellationToken)
         at MongoDB.Driver.CollectionAggregateFluent`2.ToCursor(CancellationToken cancellationToken)
         at MongoDB.Driver.IAsyncCursorSourceExtensions.ToList[TDocument](IAsyncCursorSource`1 source, CancellationToken cancellationToken)
         at Methods.ProjectWithDivideDecimal(IMongoCollection`1 items) in C:\Stuff\Documents\Programming\C#\Projects\MongoDbDivide\Program.cs:line 54
         at Program.<Main>$(String[] args) in C:\Stuff\Documents\Programming\C#\Projects\MongoDbDivide\Program.cs:line 12  This exception was originally thrown at this call stack:
          [External Code]Inner Exception 1:
      TruncationException: Truncation resulted in data loss.
      

      .NET 8.0

      C# Driver Version = 2.24.0

      MongoDB Server version = (Atlas) 6.0.14 , Region: AZURE California (westus)

      How to Reproduce

      1.  
        dotnet new console --framework net8.0
        dotnet add package MongoDB.Driver
      1. Paste the following code into the Program.cs file
      using MongoDB.Bson.Serialization.Attributes;
      using MongoDB.Bson;
      using MongoDB.Driver;
      
      const string connectionUri = "<REDACTED>";
      var client = new MongoClient(connectionUri);
      var db = client.GetDatabase("db");
      var items = db.GetCollection<Item>("items");
      
      await Methods.InsertOne(items);
      Methods.ProjectWithDivideDecimal(items);
      
      internal sealed class Item
      {
          public static Item SampleItem => new()
          {
              Balance = 1000
          };
          [BsonId]
          [BsonRepresentation(BsonType.ObjectId)]
          public string Id { get; set; } = string.Empty;
      
          [BsonElement("balance")]
          [BsonRepresentation(BsonType.Decimal128)]
          public decimal Balance { get; set; }
      
          public override string ToString()
          {
              return $"Id = {Id}, Balance = {Balance}";
          }
      }
      
      internal static class Methods
      {
          public static async Task InsertOne(IMongoCollection<Item> items)
          {
              await items.InsertOneAsync(Item.SampleItem);
          }
      
          public static void ProjectWithDivideDecimal(IMongoCollection<Item> items)
          {
              var projectStage = Builders<Item>.Projection.Expression(a => new
              {
                  a.Balance,
                  GBP = a.Balance / 1.30M
              });
      
              var aggr = items.Aggregate()
                  .Project(projectStage);
      
              var results = aggr.ToList(); // TruncationException!
              results.ForEach(Console.WriteLine);
          }
      }
      1. Run
      2. You should see an exception thrown on this line:
      var results = aggr.ToList();

      Additional Background

      I've attached a .zip file with the reproducible project.

            Assignee:
            robert@mongodb.com Robert Stam
            Reporter:
            leegrissom@gmail.com Lee Grissom
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: