【问题标题】:How to ignore null values globally by calling obj.ToBsonDocument() using MongoDB C# driver?如何通过使用 MongoDB C# 驱动程序调用 obj.ToBsonDocument() 来全局忽略空值?
【发布时间】:2021-09-08 17:27:06
【问题描述】:

史前史:我有一个从 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();
}

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

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

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

【问题讨论】:

  • 嘿 Antipod,如果它们存在并且您没有通过 null 值检查来删除它们,那么忽略它们将很困难。顺便说一句,“忽略”是什么意思,比如不插入它们或将另一个对象插入到列中作为“占位符”?
  • “忽略”我的意思是我不想在数据库中看到它们。放置假值,即不会使用的值,听起来不是一个好主意,我不想在数据库中有垃圾。并检查某些内容是否为空(如何?)并删除它听起来像是开销,或者我可能不明白你的意思。

标签: c# mongodb bson


【解决方案1】:

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

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()此约定包。

【讨论】:

  • 这很优雅,希望我早知道这个!
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

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

    • int = 0
    • 十进制 = 0
    • 布尔 = 假

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

    这是一个例子:

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

    【讨论】:

    • 这带来了另一个问题,如果我们需要忽略空数组和空值而不是int十进制布尔值怎么办?
    猜你喜欢
    • 1970-01-01
    • 2014-06-20
    • 1970-01-01
    • 2013-09-01
    • 1970-01-01
    • 2018-08-27
    • 2019-07-05
    • 1970-01-01
    相关资源
    最近更新 更多