如何使用MongoDB C#驱动程序调用obj.ToBsonDocument()来全局忽略空值?

时间:2016-08-03 15:20:53

标签: c# mongodb bson

史前史:我有一个从XML架构(XSD)生成的类层次结构(一个很大的层次结构)。

MyObj obj;

现在:我需要使用生成的类层次结构解析一个字符串值,它实际上是一个XML对象,然后我需要将该对象放入MongoDB。代码是:

private BsonDocument XmlToBson(string content)
{
    MyObj obj;
    using (var reader = new StringReader(content))
    {
        var serializer = new XmlSerializer(typeof(MyObj));
        obj = (MyObj) serializer.Deserialize(reader);
    }

    return obj.ToBsonDocument();
}

问题:层次结构中有很多null子对象,在Robomongo中看起来像这样:

Object which is null is added

我想避免将空对象添加到数据库中。我知道我可以逐个忽略它们,就像这里描述Ignoring Default Values一样,使用属性或lambda表达式。但由于层次结构庞大而复杂,我不喜欢这种方法。我懒得列出当它们具有空值时必须被忽略的所有属性。更重要的是,该类可以在将来重新生成,支持必须忽略的属性列表将是一场噩梦。

问题:无论对象在层次结构中的哪个位置,如何实现目标并忽略全局空值?我正在使用MongoDB C#驱动程序版本。 2.2。

3 个答案:

答案 0 :(得分:8)

通过注册约定包,可以在序列化时将大多数属性的效果应用于所有属性。

在注册IgnoreIfDefaultConvention下方,在序列化和反序列化时隐式将[IgnoreIfDefault]属性应用于所有属性。

var anon = new
{
    Foo = "bar",
    Baz = (string)null,
};

ConventionRegistry.Register("IgnoreIfDefault", 
                            new ConventionPack { new IgnoreIfDefaultConvention(true) }, 
                            t => true);

var bsonDocument = anon.ToBsonDocument();

这将生成仅包含Foo密钥的文档。

如果需要,您还可以在序列化后按名称Remove()此约定包。

答案 1 :(得分:1)

您还可以应用 MongoDB.Bson.Serialization.Attributes
中的[BsonIgnoreIfNull]属性 类字段的名称空间,如果您不希望在BSON文档中显示带有空值的字段。

public class Person
{
    public string Name { get; set; }

    [BsonIgnoreIfNull]
    public List<string> Children { get; set; }
}

答案 2 :(得分:0)

实际上,使用 IgnoreIfDefaultConvention 会导致意外行为,因为它会影响所有默认值。例如,上面列表中的值将不会被保存:

  • int = 0
  • 十进制 = 0
  • bool = false

如果您只想忽略空值,最好的方法是IgnoreIfNullConvention

这是一个例子:

ConventionRegistry.Register("IgnoreIfNullConvention", new ConventionPack { new IgnoreIfNullConvention(true) }, t => true);