MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

BsonSerializationException lors de la sérialisation d'un Dictionary en BSON

Le problème est que le nouveau pilote sérialise les dictionnaires en tant que document par défaut.

Le pilote MongoDB C# a 3 façons de sérialiser un dictionnaire :Document , ArrayOfArrays &ArrayOfDocuments (plus à ce sujet dans la documentation). Lorsqu'il est sérialisé en tant que document, les clés du dictionnaire sont les noms de l'élément BSON qui présente certaines limitations (par exemple, comme le suggère l'erreur, elles doivent être sérialisées en tant que chaînes).

Dans ce cas, les clés du dictionnaire sont DateTime s qui ne sont pas sérialisés en tant que chaînes, mais en tant que Date s nous devons donc choisir un autre DictionaryRepresentation .

Pour changer la sérialisation de cette propriété spécifique, nous pouvons utiliser le BsonDictionaryOptions attribut avec un DictionaryRepresentation différent :

[BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)]
public Dictionary<DateTime, int> Dictionary { get; private set; }

Cependant, nous devons le faire sur chaque membre problématique individuellement. Pour appliquer cette DictionaryRepresentation à tous les membres concernés nous pouvons mettre en place une nouvelle convention :

class DictionaryRepresentationConvention : ConventionBase, IMemberMapConvention
{
    private readonly DictionaryRepresentation _dictionaryRepresentation;
    public DictionaryRepresentationConvention(DictionaryRepresentation dictionaryRepresentation)
    {
        _dictionaryRepresentation = dictionaryRepresentation;
    }
    public void Apply(BsonMemberMap memberMap)
    {
        memberMap.SetSerializer(ConfigureSerializer(memberMap.GetSerializer()));
    }
    private IBsonSerializer ConfigureSerializer(IBsonSerializer serializer)
    {
        var dictionaryRepresentationConfigurable = serializer as IDictionaryRepresentationConfigurable;
        if (dictionaryRepresentationConfigurable != null)
        {
            serializer = dictionaryRepresentationConfigurable.WithDictionaryRepresentation(_dictionaryRepresentation);
        }

        var childSerializerConfigurable = serializer as IChildSerializerConfigurable;
        return childSerializerConfigurable == null
            ? serializer
            : childSerializerConfigurable.WithChildSerializer(ConfigureSerializer(childSerializerConfigurable.ChildSerializer));
    }
} 

Que nous enregistrons comme suit :

ConventionRegistry.Register(
    "DictionaryRepresentationConvention",
    new ConventionPack {new DictionaryRepresentationConvention(DictionaryRepresentation.ArrayOfArrays)},
    _ => true);