MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

BsonSerializationException durante la serializzazione di un Dictionary in BSON

Il problema è che il nuovo driver serializza i dizionari come documento per impostazione predefinita.

Il driver MongoDB C# ha 3 modi per serializzare un dizionario:Document , ArrayOfArrays &ArrayOfDocuments (maggiori informazioni su questo nei documenti). Quando serializza come documento le chiavi del dizionario sono i nomi dell'elemento BSON che presenta alcune limitazioni (ad esempio, come suggerisce l'errore, devono essere serializzate come stringhe).

In questo caso, le chiavi del dizionario sono DateTime s che non sono serializzate come stringhe, ma come Date Quindi dobbiamo scegliere un altro DictionaryRepresentation .

Per modificare la serializzazione di questa specifica proprietà possiamo utilizzare il BsonDictionaryOptions attributo con un diverso DictionaryRepresentation :

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

Tuttavia, dobbiamo farlo individualmente su ogni membro problematico. Per applicare questa DictionaryRepresentation a tutti i membri interessati possiamo implementare una nuova convenzione:

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));
    }
} 

Che registriamo come segue:

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