MongoDb.Driver 2.4 изменение типа данных десерилизации
У меня есть следующий класс POCO:
class MyClass {
public Objectid _id {get;set;}
public string property1 {get;set;}
public string property2 {get;set;}
public int property3 {get;set;}
}
Объект хранится в коллекции MongoDb. Данные имеют правильные типы данных в результирующем bson:
property1: "SomeString"
property2: "12345"
property3: 98765
Когда я пытаюсь запросить коллекцию:
var items = db.GetCollection<MyClass>("MyClass").AsQueryable().Select(x => x.property1 == "SomeString").ToList();
Я получаю сообщение об ошибке, указывающее, что не может быть десериализована property2: Невозможно десериализовать 'String' из BsonType 'Int64'
Я пытаюсь десериализовать строковое значение из документа bson в БД в строковое значение на моем объекте.
Почему BsonSerializer пытается преобразовать его в десятичную? В этом случае значение оказывается числовым, но поле определяется в классе как строка, поскольку значение обычно буквенно-цифровое.
Я использую пакет MongoDb.Driver v2.4, в VS2013.
1 ответ
Для изменения типа свойства Mongo вам необходимо написать собственный Serializer для этого свойства.
Это оригинальный объект, и вы сохранили несколько таких объектов в Mongo.
public class TestingObject
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int TestingObjectType { get; set; }
}
Теперь нам нужно изменить TestObjectType с int на строку
Это наш новый класс
public class TestingObject
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string TestingObjectType { get; set; }
}
Затем вы получите
Невозможно десериализовать 'String' из BsonType 'Int64'
Вам нужен сериализатор для обработки конвертации.
public class TestingObjectTypeSerializer : IBsonSerializer
{
public Type ValueType { get; } = typeof(string);
public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
if (context.Reader.CurrentBsonType == BsonType.Int32) return GetNumberValue(context);
return context.Reader.ReadString();
}
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
{
context.Writer.WriteString(value as string);
}
private static object GetNumberValue(BsonDeserializationContext context)
{
var value = context.Reader.ReadInt32();
switch (value)
{
case 1:
return "one";
case 2:
return "two";
case 3:
return "three";
default:
return "BadType";
}
}
}
Ключевой частью является метод десериализации. Только если тип int32, вы хотите запустить логику преобразования. Если тип является чем-то еще, мы будем предполагать, что это уже строка и возвращаем это значение.
Сериализация только из WriteString и любой документ, обновленный или сохраненный, будет иметь новое значение в виде строки.
Теперь вам просто нужно обновить объект, чтобы указать свойству использовать ваш сериализатор
public class TestingObject
{
public string FirstName { get; set; }
public string LastName { get; set; }
[BsonSerializer(typeof(TestingObjectTypeSerializer))]
public string TestingObjectType { get; set; }
}
В следующий раз, когда вы прочитаете его из Монго, вы не должны получить ошибку.