1

我有以下 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:无法从 BsonType 'Int64' 反序列化 'String'

我正在尝试将数据库中 bson 文档中的字符串值反序列化为对象上的字符串值。

为什么 BsonSerializer 试图将其转换为十进制?在这种情况下,该值恰好是数字,但该字段在类中定义为字符串,因为该值通常是字母数字。

我在 VS2013 中使用 MongoDb.Driver v2.4 包。

4

1 回答 1

1

对于 Mongo 属性类型更改,您需要为该属性编写自己的序列化程序。

这是原始对象,您已将其中几个对象保存到 Mongo。

public class TestingObject
{
    public string FirstName { get; set; }

    public string LastName { get; set; }

    public int TestingObjectType { get; set; }
}

现在我们需要将 TestObjectType 从 int 更改为 string

这是我们的新课

public class TestingObject
{
    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string TestingObjectType { get; set; }
}

然后你会得到

无法从 BsonType 'Int64' 反序列化 'String'

您需要的是一个序列化程序来为您处理转换。

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

下次您从 Mongo 读取它时,您应该不会收到错误消息。

于 2017-04-05T01:44:58.637 回答