使用C#读取MongoDB时如何转换GoodsList的name+value格式?
解决方案
方案一:手动转换(快速实现)
先将MongoDB数据读取为BsonDocument,再手动提取字段并转换GoodsList的格式,这种方式逻辑直观,适合快速解决需求。
步骤与代码示例
- 定义目标实体类:
public class Order { // 用BsonElement指定MongoDB中的字段名,解决大小写差异问题 [BsonElement("StatusText")] public string StatusText { get; set; } [BsonElement("goodsList")] public List<GoodsItem> GoodsList { get; set; } [BsonElement("Notes")] public string Notes { get; set; } } public class GoodsItem { public string Name { get; set; } public decimal Price { get; set; } // 添加其他需要映射的字段 }
- 读取并转换数据:
// 假设已获取MongoDB集合实例 var collection = mongoDatabase.GetCollection<BsonDocument>("your-collection-name"); var filter = Builders<BsonDocument>.Filter.Empty; var rawDocument = collection.Find(filter).FirstOrDefault(); if (rawDocument == null) return null; var order = new Order { StatusText = rawDocument.GetValue("StatusText", BsonString.Empty).AsString, Notes = rawDocument.GetValue("Notes", BsonString.Empty).AsString, GoodsList = new List<GoodsItem>() }; // 处理嵌套的goodsList数组 if (rawDocument.Contains("goodsList") && rawDocument["goodsList"] is BsonArray outerArray) { foreach (var innerArray in outerArray.OfType<BsonArray>()) { var goodsItem = new GoodsItem(); foreach (var kvDoc in innerArray.OfType<BsonDocument>()) { var fieldName = kvDoc.GetValue("name").AsString.ToLower(); var fieldValue = kvDoc.GetValue("value"); // 根据字段名映射到GoodsItem属性 switch (fieldName) { case "name": goodsItem.Name = fieldValue.AsString; break; case "price": goodsItem.Price = fieldValue.AsDecimal; break; // 新增其他字段的映射逻辑 } } order.GoodsList.Add(goodsItem); } }
方案二:自定义MongoDB序列化器(复用性高)
通过实现MongoDB的IBsonSerializer接口,自定义GoodsItem的反序列化逻辑,后续读取数据时可直接用实体类映射,无需重复编写转换代码。
步骤与代码示例
- 实现自定义序列化器:
public class GoodsItemSerializer : IBsonSerializer<GoodsItem> { public Type ValueType => typeof(GoodsItem); public GoodsItem Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { // 读取内层数组(每个内层数组对应一个GoodsItem) var innerArray = context.Reader.ReadBsonArray(); var goodsItem = new GoodsItem(); foreach (var bsonDoc in innerArray.OfType<BsonDocument>()) { var fieldName = bsonDoc["name"].AsString.ToLower(); var fieldValue = bsonDoc["value"]; switch (fieldName) { case "name": goodsItem.Name = fieldValue.AsString; break; case "price": goodsItem.Price = fieldValue.AsDecimal; break; // 其他字段映射 } } return goodsItem; } // 如果不需要将数据写回MongoDB,可直接抛出异常 public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, GoodsItem value) { throw new NotImplementedException("序列化逻辑未实现"); } // 显式实现非泛型接口方法 object IBsonSerializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { return Deserialize(context, args); } void IBsonSerializer.Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value) { Serialize(context, args, (GoodsItem)value); } }
- 绑定序列化器到实体类:
public class Order { [BsonElement("StatusText")] public string StatusText { get; set; } [BsonElement("goodsList")] // 指定自定义序列化器处理GoodsList的反序列化 [BsonSerializer(typeof(GoodsItemSerializer))] public List<GoodsItem> GoodsList { get; set; } [BsonElement("Notes")] public string Notes { get; set; } }
- 直接读取为实体类:
var collection = mongoDatabase.GetCollection<Order>("your-collection-name"); var filter = Builders<Order>.Filter.Empty; var order = collection.Find(filter).FirstOrDefault();
关键注意点
- 字段大小写匹配:MongoDB中的字段是驼峰格式(如
goodsList),实体类是帕斯卡格式,需通过[BsonElement]特性或全局配置CamelCaseElementNameConvention来匹配。 - 字段类型兼容:转换
value时要确保类型匹配(如price用AsDecimal而非AsString),避免类型转换异常。
内容的提问来源于stack exchange,提问作者Syni
相关产品推荐
相关产品推荐

