【问题标题】:Mongo C# Driver: Deserialize BsonValueMongo C# 驱动程序:反序列化 BsonValue
【发布时间】:2011-10-05 18:03:04
【问题描述】:

我在 mongodb 中有一个结构类似于此的文档:

{
  "_id": "abcdef01234",
  "Name": "Product A",
  "Dimensions": [
    {
      "Height": 32,
      "Width": 64
    },
    {
      "Height": 16,
      "Width": 32
    },
    {
      "Height": 8,
      "Width": 16
    }
  ]
}

我还定义了一个类来表示维度(上面的子文档)

public class Dimension
{
  public int Height { get; set; }
  public int Width { get; set; }
}

我正在以这种方式选择“产品 A”文档:

MongoServer srv = MongoServer.Create(myConnStr);
BsonDocument doc = srv["db"]["products"].FindOneById(ObjectId.Parse("abcdef01234"));
BsonValue dimensionsVal = doc["Dimensions"];

现在我有一个名为 dimensionsVal 的 BsonValue,它的类型为 BsonArray。我真正想要的是一个 List。如何将 dimensionsVal 转换为 List?

编辑 维度类实际上比我描述的要复杂得多。由于内存问题,我想将尺寸与产品分开。我想将 Product 保留在内存中,而不是(可能是巨大的)维度列表。因此,我不想将 List 作为 Product 类的属性。

【问题讨论】:

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


    【解决方案1】:

    这是如何做到的:

    using MongoDB.Bson.Serialization;
    
    MongoServer srv = MongoServer.Create(myConnStr);
    BsonDocument doc = srv["db"]["products"].FindOneById(ObjectId.Parse("abcdef01234"));
    BsonValue dimVal = doc["Dimensions"];
    List<Dimension> d = BsonSerializer.Deserialize<List<Dimension>>(dimVal.ToJson());
    

    【讨论】:

    • 只是给大家解释一下这段代码sn-p做了什么:首先将Value转换为JSON,一旦发生,它可以很容易地反序列化为任何对象
    【解决方案2】:

    我会像其他人建议的那样使用 List 类型的Dimensions 属性声明您的类。然后,如果您想读取 没有 的 Product,Dimensions 值会这样写:

    ObjectId productId;
    var query = Query.EQ("_id", productId);
    var fields = Fields.Exclude("Dimensions");
    var product = collection.Find(query).SetFields(fields).FirstOrDefault();
    // product.Dimensions will be null because there was no data for it
    

    当您想阅读完整的产品包括所有维度时,请写下:

    ObjectId productId;
    var query = Query.EQ("_id", productId);
    var product = collection.FindOne(query);
    // product.Dimensions will be populated this time
    

    这将比将维度读取到 BsonDocument 并使用手写代码将它们转换为 List 效率更高。这种方法会导致将数据的两个副本加载到内存中(尽管如果您不保留对 BsonDocument 版本的引用,那么之后可能很快就会对 BsonDocument 版本进行垃圾收集)。

    【讨论】:

      【解决方案3】:

      更新:

      您可能正在寻找include/exclude 功能。在 c# 驱动程序中它是这样做的:

       // load products without array of Dimensions
      MongoCursorInstance.SetFields(Fields.Exclude("Dimensions"));
      //load empty product with Dimensions and _id
      MongoCursorInstance.SetFields(Fields.Include("Dimensions"));
      

      为什么不只为产品创建类?在这种情况下,驱动程序将能够自动反序列化数据:

      class Product
      {
         [BsonId]
         public ObjectId Id { get; set; }
      
         public string Name{ get; set; }
      
         public List<Dimension> Dimensions{ get; set; }
      
      }
      
      var product = srv["db"]["products"].FindOneByIdAs<Product>();
      var dimentions = product.Dimensions;
      

      但如果你不想创建 Product 类,你可以这样:

      BsonArray dimensionsVal = doc["Dimensions"].AsBsonArray;
      
      var list = new List<Dimension>();
      foreach (BsonValue value in dimensionsVal)
      {
        var bsonDoc = (BsonDocument) value;
        var d = new Dimension();
        d.Height = bsonDoc["Height"];
        d.Width = bsonDoc["Width"];
        list.Add(d);
      }
      

      【讨论】:

      • 我希望您提出的解决方案是不必要的,即有一种方法可以自动将维度反序列化为列表。如果没有,我可以向 Dimension 类添加一个构造函数,该构造函数将 BsonDocument 作为参数,并从 BsonDocument 手动填充 Dimension。
      【解决方案4】:

      试试这个:

      public class Product
      {
         [BsonId]
         public ObjectId Id { get; set; }
      
         public string Name{ get; set; }
      
         public List<DimensionDoc> Dimensions{ get; set; }
      }
      
      public class DimensionDoc
      {
         public int Height { get; set; }
         public int Width { get; set; }
      
      }
      
      Product product = srv["db"]["products"].FindOneByIdAs<Product>(ObjectId.Parse("abcdef01234"));
      

      product.Dimensions 现在将包含您需要的 List。

      【讨论】:

      • 维度类实际上比我描述的要复杂得多,并且包含对另一个文档的引用。由于内存问题,我想将尺寸与产品分开。我想将产品保留在内存中,而不是尺寸。这就是为什么我要尝试与您描述的不同。
      • 为什么不创建另一个包含产品所有字段但不包含维度的类。然后,从数据库加载文档后,只需将字段复制到该对象,维度除外。然后你把那个对象放在内存中。您的维度列表是否太大,可能会占用太多内存?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-09
      • 1970-01-01
      相关资源
      最近更新 更多