I have data in my MongoDB where I am storing a nullable int, most often as null. My model on the C# side has the variable as int? MaterialID.
When I run .Query.FirstOrDefault(), I get an error "Input string was not in a correct format." whenever it tries to read the null value from Mongo (ints work fine).
I managed to get around this by changing my int? to a string and then later casting that back to an int?, but that's a horrible hack that I really don't like. Anyone have any ideas as to how I can read null from Mongo into my int? on the C# side?
Thanks.
My 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"
}
]
You are storing the MaterialID field as a string in the database (type 2). Of course when you try to assign a string value to a nullable integer you have an error. Note: even null is stored as a string with the text "null" . I recommend that you start by fixing the data in your database. You can do it from 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}}); })Note: in your json docs you don't have the _id field, but I'm guessing it's there instead of the ID field. Anyway, you can adjust the script to your needs.
After changing the field type, its mapping to nullable int will work correctly.
By the way, there is another option in case for some reason you cannot correct the data in the database. Can you use custom BSON serializer which will convert int? to the chain and vice versa:
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); } }And assign this serializer to your property
[BsonSerializer(typeof(NullableIntAsStringSerializer))] public int? MaterialID { get; set; }