如何将对默认构造函数的“空”引用从 MongoDB 映射到 POCO

本文关键字:引用 MongoDB 映射 POCO 默认 构造函数 | 更新日期: 2023-09-27 18:31:25

我正在将MongoDB文档映射到C#对象(有关一些背景,请参阅此问题),并且一切正常,但是我开始发现一些为空的条目。原因是XML以前只有<VehicleEntry></VehicleEntry>标记,因此它作为"null"插入到BsonDocument的数组中。

我可以理解这是预期的行为,但是当我将其映射到我编写的VehicleEntry类时,它显示为空对象。在我的映射类中,我列出了一堆 BsonDefaultValues,甚至添加了一个默认构造函数,但看起来如果数据库中的值为 'null',它将创建一个 'null' 引用对象。

如何进行设置以将空引用与所有默认值匹配到对象?

如何将对默认构造函数的“空”引用从 MongoDB 映射到 POCO

如果您创建自己的 BsonSerializers 并将其分配给 VehicleEntry 类型,那么您将能够说该值是否为 null,然后返回一个default(VehicleEntry)

[TestFixture]
public class StackQuestionTest
{
    [Test]
    public void GivenABsonDocumentWithANullForAnPossibleEmbeddedDocument_When_ThenAnInstanceIsSetAsTheEmbeddedDocument()
    {
        BsonSerializer.RegisterSerializationProvider(new VehicleEntryBsonSerializationProvider());
        var document = new BsonDocument()
        {
            {"OtherProperty1", BsonString.Create("12345")},
            {"OtherProperty2", BsonString.Create("67890")},
            {"VehicleEntry", BsonNull.Value},
        };
        var rootObject = BsonSerializer.Deserialize<RootObject>(document);
        Assert.That(rootObject.OtherProperty1, Is.EqualTo("12345"));
        Assert.That(rootObject.OtherProperty2, Is.EqualTo("67890"));
        Assert.That(rootObject.VehicleEntry, Is.Not.Null);
        Assert.That(rootObject.VehicleEntry.What, Is.EqualTo("Magic"));
    }
}
public class VehicleEntrySerializer : BsonClassMapSerializer<VehicleEntry>
{
    public override VehicleEntry Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        if (context.Reader.GetCurrentBsonType() == BsonType.Null)
        {
            context.Reader.ReadNull();
            return new VehicleEntry();
        }
        return base.Deserialize(context, args);
    }
    public VehicleEntrySerializer(BsonClassMap classMap) : base(classMap)
    {
    }
}
public class VehicleEntryBsonSerializationProvider : IBsonSerializationProvider
{
    public IBsonSerializer GetSerializer(Type type)
    {
        if (type == typeof(VehicleEntry))
        {
            BsonClassMap bsonClassMap = BsonClassMap.LookupClassMap(type);
            return new VehicleEntrySerializer(bsonClassMap);
        }
        return null;
    }
}

public class RootObject
{
    public string OtherProperty1 { get; set; }
    public string OtherProperty2 { get; set; }
    public VehicleEntry VehicleEntry { get; set; }
}
public class VehicleEntry
{
    public string What { get; set; } = "Magic";
}

请参阅 http://mongodb.github.io/mongo-csharp-driver/2.0/reference/bson/serialization/

一种解决方案是将 LINQ 更改为仅返回列表中不为 null 的值:

var results = collection.AsQueryable()
   .Where(v => v.ProjectName.Equals("input")
   .SelectMan(v => v.VehicleEntries)
   .Where(i => i != null)
   .ToList();

这并不能解决 null 值存在的问题,但它会在任何结果中呈现它,并在显示数据时避免 NPE。