简体   繁体   English

Mongo C#Driver:反序列化BsonArray

[英]Mongo C#Driver:Deserialize BsonArray

I have a document in mongodb that is structured similar to this: 我在mongodb中有一个文档,其结构类似于此:

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

how to make a mapping class to serialize this document? 如何制作一个映射类来序列化此文档?

I also have a class defined to represent dimensions (the sub document from above) 我也定义了一个代表尺寸的类(上面的子文档)

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;}
}

how to query element "b" in class STObject? 如何在类STObject中查询元素“ b”?

In order to deserialize class hierarchy , document should contain type discriminator field, which tells which type of subclass should be instantiated. 为了反序列化类层次结构 ,文档应包含类型鉴别符字段,该字段指示应实例化哪种类型的子类。 By default this field has name _t . 默认情况下,该字段的名称为_t But if you already have documents with schema as above and can't change it, then you should override discriminator convention which is used by Mongo. 但是,如果您已经拥有具有上述架构的文档,并且无法更改它,那么您应该覆盖Mongo使用的区分符约定。

Looks like you can use subBusinessName field as type discriminator for sub business types. 看起来您可以将subBusinessName字段用作子业务类型的类型区分subBusinessName In order to do that, you should remove this field from base type: 为此,您应该从基本类型中删除此字段:

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

And you should provide discriminator values for subtypes: 并且您应该为子类型提供鉴别符值:

[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; }
}

And final step - create custom convention to make mongo look on this discriminator field for instantiating correct sub class type: 最后一步-创建自定义约定,使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;
    }
}

Now set this convention for your base type serialization: 现在为您的基本类型序列化设置以下约定:

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

And you can serialize and deserialize documents in your exact format. 您可以按照您的确切格式序列化和反序列化文档。

UPDATE: Querying: 更新:查询:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM