[CSHARP-2607] BsonDefaultValue does not accept decimals. Created: 09/May/19  Updated: 27/Oct/23  Resolved: 13/May/19

Status: Closed
Project: C# Driver
Component/s: None
Affects Version/s: 2.8.0
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Tim Arheit Assignee: Robert Stam
Resolution: Works as Designed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

MongoDB version 4.0.6
.Core 2.2



 Description   

[BsonDefaultValue(0m)]  shows the compilation error: Error CS0182 An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type

However if used with an integer in an object plroperty such as:

[BsonDefaultValue(0)]

public decimal Amount { get; set; }

And then subsequently loading a record with no value for Amount from the database,   the error Unable to cast object of type 'System.Int32' to type 'System.Decimal' is thrown.

So it appears that you cannot set a default of the correct type for decimal currently.

 

 



 Comments   
Comment by Robert Stam [ 13/May/19 ]

Due to the rules of the C# language specifying what types may be used as values passed to attributes, [BsonDefaultValue] cannot be used with decimal.

To work around this, you can set the default value in code instead of via attributes.

Consider this sample class (I'm using 1 instead of 0 for the default value for testing because 0 is already the default).

[BsonDefaultValue(1)]
public int I { get; set; }
 
// [BsonDefaultValue(1m)] // can't do this due to C# language rules
public decimal D { get; set; }

The following code initializes the default value and tests it:

[Fact]
public void Test()
{
    BsonClassMap.RegisterClassMap<C>(cm =>
    {
        cm.AutoMap();
        cm.GetMemberMap(x => x.D).SetDefaultValue(1m);
    });
 
    var json = "{ }";
    var c = BsonSerializer.Deserialize<C>(json);
 
    c.I.Should().Be(1);
    c.D.Should().Be(1m);}

 If you use this approach be sure to put the call to RegisterClassMap early in your initialization code and ensure it is only run once.

 

 

Comment by Tim Arheit [ 09/May/19 ]

FYI,  for now my workaround effectively is to use a nullable private property and [BsonIgnoreIfNull] to simulate [BsonDefaultValue(0m)] [BsonIgnoreIfDefault]

 

[BsonIgnoreIfNull]
private decimal? _Amount{get;set;} = null;
 
[BsonIgnore]
public decimal Amount
{
   get => _Amount?? 0;    
   set => _Amount= value == 0m ? (decimal?)null : value;
}

 

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