【问题标题】:BsonExtraElements Dictionary<string, Object> and custom classes as value fails serializationBsonExtraElements Dictionary<string, Object> 和自定义类作为值序列化失败
【发布时间】:2018-01-04 19:49:19
【问题描述】:

具有以下类:

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 cannot be mapped to a BsonValue'

如果我删除 [BsonExtraElements] 属性,一切都会正常,文章最终会进入数据库。为什么是这样?该属性如何防止序列化?因为属性不存在,所以我的这个自定义类可以被驱动序列化。

使用驱动程序版本 2.4.4

【问题讨论】:

  • 我已经在 mongodb 的jira 上报告了这个。他们已经调查并回复:It's not really intended behavior. We currently assume that all the values in the BsonExtraElements dictionary are either instances of BsonValue or trivially convertible to BsonValue. We should be able to convert more complex values like your Bird class by using a serializer. We will consider supporting this in a future release.

标签: c# mongodb dictionary bson


【解决方案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() }

【讨论】:

  • 感谢您的回答!但是,您链接的文档很旧。我正在使用 2.4 版本的 C# 驱动程序。可以将[BsonExtraElements] 添加到dictionaryTo do so, you must have a property of type BsonDocument (or IDictionary&lt;string, object&gt;)
  • 哦,你没有指定驱动程序版本,所以我很难做到。您是否尝试将成员重命名为 ExtraElements?
  • 我试了一下,但在重命名字段时我仍然遇到同样的错误。我还编辑了问题以包含驱动程序版本。
  • 查看编辑。为了便于阅读,我编辑了答案。希望现在解决=)
  • 感谢您帮助寻找解决方案。这会将其正确添加到数据库中,但在检索时它会被填充到 Dictionary&lt;string, Object&gt; 中,其中包含 _n、_s、_a 键而不是 Bird 对象。这是不幸的,因为我希望将我添加到数据库中的任何类反序列化回该特定类。但我们正在取得进展:)
【解决方案2】:

改用[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"
        },
        ...
    }

}

【讨论】:

    猜你喜欢
    • 2011-10-17
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 2012-03-01
    • 1970-01-01
    • 2015-11-07
    • 2017-06-12
    • 2013-01-16
    相关资源
    最近更新 更多