. Net Базовый драйвер MongoDb - Исключение ReadBsonType можно вызывать только тогда, когда State имеет тип, а не когда State является значением - PullRequest
1 голос
/ 26 апреля 2020

Я рефакторинг кода, который извлекает документ из коллекции MongoDb как BsonDocument. Поскольку C# предлагает нам возможность сделать наш код более безопасным с помощью строго типизированного класса, я хотел создать класс для представления документа, сохраненного в коллекции.

Проблема в том, что у меня есть свойство, которое должен быть сохранен в коллекции как документ, иногда как-то сохраняется как пустая строка. Поэтому, когда MongoDbDriver пытается десериализовать его, я получаю исключение, в котором говорится, что ожидался вложенный документ вместо строки.

В этом сценарии я хотел установить значение свойства как null.

Итак, я попытался внедрить мой десериализатор для обхода этого сценария:

Мой класс:

[BsonIgnoreExtraElements]
public class ExampleModel
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public ObjectId Id { get; set; }

    .
    .
    .

    [BsonElement("usedTemplate")]
    [BsonSerializer(typeof(ExampleModelTemplateSerializer ))]
    public TemplateModel Template { get; set; }
}

Сериализатор

public class ExampleModelTemplateSerializer : SerializerBase<TemplateModel>
{
    public override TemplateModel Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        return context.Reader.CurrentBsonType == BsonType.String
            ? null 
            : base.Deserialize(context, args);
    }
}

Исключение

Сообщение: ReadBsonType может быть вызван только тогда, когда State имеет тип, а не когда State является значением.

1 Ответ

1 голос
/ 27 апреля 2020

Причина, по которой вы получаете эту ошибку, заключается в том, что ваш context.Reader должен все равно прочитать строку, чтобы вы могли вызвать context.Reader.ReadString();, но вернуть null, когда вы sh.

Следующая проблема заключается в том, что вы вызываете base.Deserialize() для SerializerBase<T>, который является абстрактным классом, и будет выброшено исключение (реализация здесь ). Поэтому вам нужно выполнить десериализацию, позвонив по номеру BsonSerializer:

public class ExampleModelTemplateSerializer : SerializerBase<TemplateModel>
{
    public override TemplateModel Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        if (context.Reader.CurrentBsonType == BsonType.String)
        {
            context.Reader.ReadString();
            return null;
        }

        return BsonSerializer.Deserialize<TemplateModel>(context.Reader);
    }
}
...