Answer a question

I have an enum

public enum MyEnum : uint
    {
        ValueA = 1233104067,
        ValueB= 1119849093,
        ValueC= 2726580491
}

Whenever I create some class with this enum and try to store it into the database. For example

class MyClass {
    public MyEnum newValue = MyEnum.ValueC;
}

It will crash the program with this error

Unhandled Exception: System.OverflowException: Value was either too large or too small for an Int32.
   at System.Convert.ThrowInt32OverflowException()
   at System.UInt32.System.IConvertible.ToInt32(IFormatProvider provider)
   at MongoDB.Bson.Serialization.Serializers.EnumSerializer`1.Serialize(BsonSerializationContext context, BsonSerializationArgs args, TEnum value)

It tries to convert uint values to int, but they are too big and it throws exception.

How do I fix this problem?

Thanks.

Answers

MongoDB stores data as BSON, which doesn't have unsigned integer types.

You have three options:

  1. Annotate your unsigned types.

    If using driver v2.4.3 or earlier:

    public class MyClass
    {
        [BsonRepresentation(BsonType.Int32, AllowOverflow = true)]
        public MyEnum Value1 = MyEnum.ValueC;
    
        [BsonRepresentation(BsonType.Int32, AllowOverflow = true)]
        public uint Value2 = uint.MaxValue;
    }
    

    Unfortunately the serializer in driver v2.4.4 and later doesn't respect AllowOverflow, throwing an exception anyway(tested and confirmed, thanks to dnickless for pointing this out). Here's a workaround (at the expense of some wasted space):

    public class MyClass
    {
        [BsonRepresentation(BsonType.Int64)]
        public MyEnum Value1 = MyEnum.ValueC;
    
        [BsonRepresentation(BsonType.Int64)]
        public uint Value2 = uint.MaxValue;
    }
    
  2. Use signed types and convert where appropriate.

    // Defaults to int.
    public enum MyEnum
    {
        ValueA = 1233104067,
        ValueB = 1119849093,
        ValueC = unchecked((int)2726580491)
    }
    
    // Usage.
    uint a = (uint)MyEnum.ValueA;
    uint b = (uint)MyEnum.ValueB;
    uint c = unchecked((uint)MyEnum.ValueC);
    uint d = (uint)document["MyProperty"].AsInt32; // Reading from a BsonDocument.
    
  3. Serialize manually(UInt32Serializer, UInt64Serializer, etc).

Logo

MongoDB社区为您提供最前沿的新闻资讯和知识内容

更多推荐