MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

BsonSerializationException ao serializar um Dictionary para BSON


O problema é que o novo driver serializa os dicionários como um documento por padrão.

O driver MongoDB C# tem 3 maneiras de serializar um dicionário:Document , ArrayOfArrays &ArrayOfDocuments (mais sobre isso nos documentos). Quando ele é serializado como um documento, as chaves do dicionário são os nomes do elemento BSON que possui algumas limitações (por exemplo, como sugere o erro, elas devem ser serializadas como strings).

Neste caso, as chaves do dicionário são DateTime s que não são serializados como strings, mas como Date s, então precisamos escolher outro DictionaryRepresentation .

Para alterar a serialização desta propriedade específica podemos usar o BsonDictionaryOptions atributo com um DictionaryRepresentation diferente :
[BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)]
public Dictionary<DateTime, int> Dictionary { get; private set; }

No entanto, precisamos fazer isso em cada membro problemático individualmente. Para aplicar esta DictionaryRepresentation para todos os membros relevantes, podemos implementar uma nova convenção:
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 registramos da seguinte forma:
ConventionRegistry.Register(
    "DictionaryRepresentationConvention",
    new ConventionPack {new DictionaryRepresentationConvention(DictionaryRepresentation.ArrayOfArrays)},
    _ => true);