BsonExtraElements Dictionary <string,object =“”>和自定义类作为值失败序列化

时间:2017-09-06 15:28:20

标签: c# mongodb dictionary bson

拥有以下课程:

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

    public string Name { get; set; }

    [BsonExtraElements()]
    public Dictionary<string, Object> OtherData { get; set; }
}

我想将此对象添加到字典并写入数据库:

public class Bird
{
    [BsonElement("_n")]
    [BsonRequired]
    public string Name { get; set; }
    [BsonElement("_s")]
    [BsonRequired]
    public string Species { get; set; }
    [BsonElement("_a")]
    [BsonRequired]
    public int Age { get; set; }
}

var col = db.GetCollection<Article>("articles");

var art = new Article
{
    Name = "Blu"
};

art.OtherData = new System.Collections.Generic.Dictionary<string, object>()
{
    { "bird" , new Bird { Name = "Jerry", Age = 4, Species = "European starling" } }
};

col.InsertOne(art);

然而,这失败并出现以下异常:System.ArgumentException:'.NET type Bird无法映射到BsonValue'

如果我删除[BsonExtraElements]属性,一切顺利,文章最终会在数据库中。为什么是这样?该属性如何防止序列化?因为该属性不在那里,我的这个自定义类可以由驱动程序序列化。

使用驱动程序版本2.4.4

2 个答案:

答案 0 :(得分:1)

官方文件(http://mongodb.github.io/mongo-csharp-driver/1.11/serialization/):

  

您可以将类设计为能够处理反序列化期间可能在BSON文档中找到的任何额外元素。为此,您必须具有 BsonDocument 类型的属性,并且必须将该属性标识为应该包含任何额外元素的属性(或者您可以将属性命名为“ExtraElements”,以便默认的ExtraElementsMemberConvention会自动找到它。

public MyClass {
// fields and properties
[BsonExtraElements]
public BsonDocument CatchAll { get; set; }
}

长话短说,当你使用[BsonExtraElements]标签时,它需要是BsonDocument类型。

干杯!

编辑:我通过添加

来实现它
{ "bird" , new Bird { Name = "Jerry", Age = 4, Species = "European starling" }.ToBsonDocument() }

答案 1 :(得分:-1)

使用 [BsonDictionaryOptions(DictionaryRepresentation.Document)] 代替

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

    public string Name { get; set; }

    [BsonDictionaryOptions(DictionaryRepresentation.Document)]
    public Dictionary<string, Object> OtherData { get; set; }
}

这将生成类似

的JSON
{
    "_id": ObjectId("5a468f3e28fad22e08c4fa6b"),
    "Name": "Sanjay",
    "OtherData": {
        "stringData": "val1",
        "boolVal": true,
        "someObject": {
            "key1": "val1",
            "key2": "val2"
        },
        ...
    }

}