sql >> Base de Datos >  >> NoSQL >> MongoDB

BsonSerializationException al serializar un Dictionary a BSON

El problema es que el nuevo controlador serializa los diccionarios como un documento de manera predeterminada.

El controlador MongoDB C# tiene 3 formas de serializar un diccionario:Document , ArrayOfArrays &ArrayOfDocuments (más sobre eso en los documentos). Cuando se serializa como un documento, las claves del diccionario son los nombres del elemento BSON que tiene algunas limitaciones (por ejemplo, como sugiere el error, deben serializarse como cadenas).

En este caso, las claves del diccionario son DateTime s que no se serializan como cadenas, sino como Date s por lo que debemos elegir otra DictionaryRepresentation .

Para cambiar la serialización de esta propiedad específica, podemos usar BsonDictionaryOptions atributo con una DictionaryRepresentation diferente :

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

Sin embargo, necesitamos hacer eso en cada miembro problemático individualmente. Para aplicar esta DictionaryRepresentation a todos los miembros relevantes podemos implementar una nueva convención:

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 de la siguiente manera:

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