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

How to ignore null values globally by calling obj.ToBsonDocument() using MongoDB C# driver?

Prehistory:我有一个 class 层次结构(一个大层次结构),它是从 XML 模式(XSD)生成的。

MyObj obj;

现在:我需要使用生成的class层次结构来解析一个字符串值,它实际上是一个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();
}

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

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

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

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

下面的IgnoreIfNullConvention被注册,在序列化和反序列化时隐式地将[IgnoreIfNull]属性应用到所有属性。

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

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

var bsonDocument = anon.ToBsonDocument();

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

如果需要,您也可以在序列化后按名称Remove()此会议包。

您还可以应用 MongoDB.Bson.Serialization.Attributes
中的 [BsonIgnoreIfNull] 属性 如果您不想在 BSON 文档中显示具有空值的字段,则将命名空间添加到 class 字段。

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

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

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

  • 整数 = 0
  • 十进制 = 0
  • bool = false

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

这是一个例子:

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