添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

C# - Loading data (enum stored as string) from MongoDB throw exception if cannot be mapped back to enum, for example old enum value has been deleted

Ask Question

I need to store enums as string in MongoDB , which is fine, but I need to able to handle changes within the enum .

For example, if you have the following enum

enum CarType {
  SportCar,
  Hatchback

If I delete SUV and I try to load a record from MongoDB that is of CarType SUV, it will throw an exception, because it is unable to map it back to enum from the string. I need to be able to handle this gracefully, like have an enum value unknown and use that as a fall back value.

Is there a way to specify a custom mapper for only specify columns within MongoDB? For example the car entity has multiple string values, but only the CarType which is an enum in our back end and stored as string in our MongoDB. So when loading data from DB, use a customer mapper only for the CarType property that will not throw and exception, instead map it to CarType.Unkown

First you need to define the unknown enum as the first enum. I myself prefer storing them as explicit ints to prevent renaming of enums corrupt the database, but that is not nessecary in your case.

enum CarType {
  Unknown
  SportCar,
  Hatchback

Then you need to write and register a custom deserializer for your enum in order to implement the fallback to "unknown" as this. It will try to parse your database value to the enum and fallbacks to default (Unknown) if unable to parse it.

 public class CustomEnumSerializer<TEnum> : MongoDB.Bson.Serialization.Serializers.EnumSerializer<TEnum>
            where TEnum : struct
            public override TEnum Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
                var type = context.Reader.GetCurrentBsonType();
                string val;
                switch (type)
                    case BsonType.String:
                        val = context.Reader.ReadString() ?? "";
                        break;
                    case BsonType.Int32:
                        val = context.Reader.ReadInt32().ToString();
                        break;
                    case BsonType.Int64:
                        val = context.Reader.ReadInt64().ToString();
                        break;
                    case BsonType.Null:
                        return default(TEnum);
                    default:
                        return base.Deserialize(context, args);
                if (Enum.TryParse(val, true, out TEnum result) && Enum.IsDefined(typeof(TEnum), result))
                    return result;
                return default(TEnum);

Register the custom serializer as:

BsonClassMap.RegisterClassMap<ClassThatHoldsTheProperty>(ms =>
                ms.AutoMap();
                ms.GetMemberMap(i => i.CarTypeProperty)
                    .SetSerializer(new CustomEnumSerializer<CarType>());
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.