Mongo C#驱动程序:反序列化BsonArray

时间:2013-10-24 10:09:13

标签: c# mongodb

我在mongodb中有一个类似于以下内容的文档:

{
    "_id":xxxxx,
    "business":[{
            "subBusiness":[{
                "subBusinessName":"Abusiness",
                "a":"aaaa"
            },{
                "subBusinessName":"Bbusiness",
                "b":"bbbbb",
                "c":"ccccc"
                }]
        }]
}

如何使映射类序列化此文档?

我还有一个用于表示维度的类(上面的子文档)

class STObject{
    [BsonId]
    public ObjectId id{get;set;}
    [BsonElement("business")]
    public List<Business> BusinessList{get;set;}
}
class Business  {   
    [BsonElement("subBusiness")]
    public List<SubBusiness> SubBuiness { get; set; }
}
[BsonDiscriminator(RootClass = true)]
[BsonKnownTypes(typeof(CSSubBusiness),typeof(ApproSubBusiness))]
public class SubBusiness {
    [BsonElement("subBusinessName")]
    public string SubBusinessName{get;set;}
}
public class AsubBusiness:SubBusiness{
    [BsonElement("a")]
    public string A{get;set;}   
}
public class BsubBusiness:SubBusiness{
    [BsonElement("b")]
    public string B{get;set;}
    [BsonElement("c")]
    public string C{get;set;}
}

如何查询类STObject中的元素“b”?

1 个答案:

答案 0 :(得分:2)

为了deserialize class hierarchy,文档应该包含type discriminator字段,它告诉应该实例化哪种类型的子类。默认情况下,此字段的名称为_t。但是如果您已经拥有上述架构的文档并且无法更改它,那么您应该覆盖Mongo使用的鉴别器约定。

看起来您可以使用subBusinessName字段作为子业务类型的类型鉴别器。为此,您应该从基类型中删除此字段:

[BsonDiscriminator(RootClass = true)]
[BsonKnownTypes(typeof(AsubBusiness), typeof(BsubBusiness))] // btw check types
public class SubBusiness
{        
}

你应该为子类型提供鉴别器值:

[BsonDiscriminator("Abusiness")] // provide discriminator value here
public class AsubBusiness : SubBusiness
{
    [BsonElement("a")]
    public string A { get; set; }
}

[BsonDiscriminator("Bbusiness")]
public class BsubBusiness : SubBusiness
{
    [BsonElement("b")]
    public string B { get; set; }
    [BsonElement("c")]
    public string C { get; set; }
}

最后一步 - 创建自定义约定,让mongo看看这个鉴别器字段,以实例化正确的子类类型:

public class SubBusinessDiscriminatorConvention : IDiscriminatorConvention
{
    public string ElementName
    {
        get { return "subBusinessName"; }
    }

    public Type GetActualType(BsonReader bsonReader, Type nominalType)
    {
        var bookmark = bsonReader.GetBookmark();
        bsonReader.ReadStartDocument();
        var actualType = nominalType;
        if (bsonReader.FindElement(ElementName))
        {
            var discriminator = (BsonValue)BsonValueSerializer.Instance.Deserialize(bsonReader, typeof(BsonValue), null);
            actualType = BsonSerializer.LookupActualType(nominalType, discriminator);
        }
        bsonReader.ReturnToBookmark(bookmark);
        return actualType;
    }

    public BsonValue GetDiscriminator(Type nominalType, Type actualType)
    {
        var classMap = BsonClassMap.LookupClassMap(actualType);
        return classMap.Discriminator;
    }
}

现在为基本类型序列化设置此约定:

BsonSerializer.RegisterDiscriminatorConvention(typeof(SubBusiness), 
    new SubBusinessDiscriminatorConvention());

您可以按照确切的格式序列化和反序列化文档。

更新:查询:

var collection = test.GetCollection<STObject>("collectionName");
var sto = collection.FindOne(Query.EQ("_id", new ObjectId("xxxxx")));
var businessList = sto.BusinessList.FirstOrDefault();
var bsub = businessList.SubBuiness.OfType<BsubBusiness>().FirstOrDefault();
var b = bsub.B; // returns bbbbb