使用 MongoDB C# 驱动程序将 null 读入可空 int

Reading null into a nullable int with MongoDB C# driver

我的 MongoDB 中有数据,我在其中存储可为 null 的 int,通常为 null。我在 C# 端的模型的变量为 int? MaterialID.

当我 运行 .Query.FirstOrDefault() 时,每当它试图从 Mongo 读取空值时我都会收到错误 "Input string was not in a correct format."(整数工作正常)。

我设法通过更改我的 int 来解决这个问题?到一个字符串,然后再将其转换回一个 int?,但这是一个我真的不喜欢的可怕 hack。任何人都知道如何将 Mongo 中的 null 读入我的 int 中?在 C# 方面?

谢谢。

我的JSON:

 "Collection" : {
        "List" : [ 
            {
                "ID" : "40",
                "StartDate" : ISODate("2013-01-01T00:00:00.000Z"),
                "EndDate" : ISODate("2013-12-31T00:00:00.000Z"),
                "MaterialID" : "3"
            }, 
            {
                "ID" : "40",
                "StartDate" : ISODate("2014-01-01T00:00:00.000Z"),
                "EndDate" : ISODate("2014-09-30T00:00:00.000Z"),
                "MaterialID" : "null"
            }
        ]

您正在将 MaterialID 字段作为字符串存储在数据库中(类型 2)。当然,当您尝试将字符串值分配给可为空的整数时,您会出错。注意:即使 null 也存储为带有文本 "null" 的字符串。我建议您从修复数据库中的数据开始。您可以从 mongo shell:

> db.collection.find({MaterialID:{$type:2}}).forEach(
    function(doc){ 
       var materialId = (doc.MaterialID == "null") ? null : new NumberInt(doc.MaterialID);
       db.collection.update({_id:doc._id},{$set:{MaterialID: materialId}});
    })

注意:在您的 json 文档中没有 _id 字段,但我假设它在那里而不是 ID 字段。无论如何,您可以根据需要调整脚本。

更改字段类型后,您映射到可为空的 int 将正常工作。


顺便说一句,如果由于某种原因您无法修复数据库中的数据,还有另一种选择。您可以使用将转换 int 的自定义 BSON 序列化程序?字符串,反之亦然:

public class NullableIntAsStringSerializer : SerializerBase<int?>
{
    public override void Serialize(
        BsonSerializationContext context, BsonSerializationArgs args, int? value)
    {
        context.Writer.WriteString(value.HasValue ? value.ToString() : "null");
    }

    public override int? Deserialize(
        BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        var str = context.Reader.ReadString();
        return str == "null" ? (int?)null : Int32.Parse(str);
    }
}

并将此序列化程序分配给您的 属性

[BsonSerializer(typeof(NullableIntAsStringSerializer))]
public int? MaterialID { get; set; }