【问题标题】:C# MongoDb serialization of Dictionary<string, object>Dictionary<string, object> 的 C# MongoDb 序列化
【发布时间】:2017-06-12 00:24:31
【问题描述】:

我的数据库中有一个用于记录事件的集合。每种类型的事件都有一组不同的数据。我用以下类定义了它:

[CollectionName("LogEvent")]
public class LogEvent
{
    public LogEvent(string eventType)
    {
        EventType = eventType;
        EventData = new Dictionary<string, object>();
    }

    public string EventType { get; private set; }
    [BsonExtraElements]
    public IDictionary<string, object> EventData { get; private set; }
}

现在 - 这在某种程度上非常有效。只要EventData字典的元素是简单类型...

var event = new LogEvent("JobQueues"){
    EventData = new Dictionary<string, object>(){
        { "JobId": "job-123" },
        { "QueueName": "FastLane" }
    }
}

_mongoCollection.InsertOne(event);

...我得到类似的 mongo 文档

{
  _id: ObjectId(...),
  EventType: "JobQueued",
  JobId: "job-123",
  QueueName: "FastLane"
}

但是,一旦我尝试向字典中添加自定义类型,事情就会停止工作。

var event = new LogEvent("JobQueues"){
    EventData = new Dictionary<string, object>(){
        { "JobId": "job-123" },
        { "QueueName": "FastLane" },
        { "JobParams" : new[]{"param-1", "param-2"}},
        { "User" : new User(){ Name = "username", Age = 10} }
    }
}

这给了我像".NET type ... cannot be mapped to BsonType."这样的错误

如果我删除 [BsonExtraElements] 标记和 [BsonDictionaryOptions(DictionaryRepresentation.Document)] 它将开始序列化内容而不会出错,但它会给我一个完全不同的文档,我不喜欢..

{
  _id: ObjectId(...),
  EventType: "JobQueued",
  EventData: {      
      JobId: "job-123",
      QueueName: "FastLane",
      User: {
       _t: "User",
       Name: "username",
       Age: 10
      },
      JobParams : {
       _t: "System.String[]",
       _v: ["param-1", "param-2"]
      }
   }
}

我想要的是以下结果:

{
  _id: ObjectId(...),
  EventType: "JobQueued",
  JobId: "job-123",
  QueueName: "FastLane",
  User: {
    Name: "username",
    Age: 10
  },
  JobParams : ["param-1", "param-2"]
}

有人知道如何实现吗?

(我使用的是 C# mongodriver v2.3)

【问题讨论】:

    标签: c# .net mongodb serialization mongodb-.net-driver


    【解决方案1】:

    MongoDriver 也是如此,因为它需要类型的信息才能将其反序列化。 您可以做的是为 User 类编写并注册您自己的 CustomMapper:

    public class CustomUserMapper : ICustomBsonTypeMapper
    {
        public bool TryMapToBsonValue(object value, out BsonValue bsonValue)
        {
            bsonValue = ((User)value).ToBsonDocument();
            return true;
        }
    }
    

    启动程序的某处:

    BsonTypeMapper.RegisterCustomTypeMapper(typeof(User), new CustomUserMapper());
    

    这会起作用,而且我已经成功地按照你的需要序列化你的数据。

    但是:当你想反序列化它时,你会得到你的User 类为Dictionary,因为驱动程序没有关于如何反序列化它的信息:

    【讨论】:

    • 反序列化不是问题。这是一个“仅附加”的集合,在极少数情况下会回读某些内容,它将通过自定义投影进行。无论如何 - 自定义序列化程序不是一个好的选择,因为其中一点是能够将“任何内容”添加到日志中。
    • 我有一种解决方法,首先使用 json.net 将数据序列化为 json,然后让 mongo 创建 json 的 bsondocument。它有点工作,但不是最佳解决方案......
    • @Vegar 也许您的解决方法是最好的解决方案。 MongoDrive 可以将任何内容添加到集合中,但它希望确保能够以准确的 sam 形式将其取回,为此使用类型描述符。
    猜你喜欢
    • 2016-08-27
    • 2013-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-10
    • 1970-01-01
    • 2011-10-17
    相关资源
    最近更新 更多