NewbieCoder NewbieCoder - 1 month ago 19
C# Question

Unable to cast object of type 'MongoDB.Bson.Serialization.Serializers.DateTimeSerializer' to type 'MongoDB.Bson.Serialization.IBsonSerializer`

While searching for the solution I got this and this but the concept was not clear to me so couldn't implement it :(.
This error occurs when I try to update values in the database(specifically for datetime objects). Below is the code that I'm using:-

var update = Builders<Model>.Update
.Set(t => t.startdate, BsonValue(objModel.startdate));
var result = model.UpdateOne(query, update);


and BonValue function is as follows:-

private static BsonValue BsonValue(object obj)
{
if (obj == null)
return (BsonValue)obj ?? BsonNull.Value;
else if (obj.GetType() == typeof(string))
return new BsonString(obj.ToString());
else if (obj.GetType() == typeof(DateTime))
return new BsonDateTime(DateTime.SpecifyKind(DateTime.Parse(obj.ToString()), DateTimeKind.Utc));
else if (obj.GetType() == typeof(int))
return new BsonInt32(int.Parse(obj.ToString()));
else
return (BsonValue)obj;
}


I think this is because I have started using upgraded packages of mongoDB.Bson and mongoDB.Driver. Current version is 2.3.0

any help would be greatly appreciated.

Edit

1) while Inserting data what i do is as follows:-

BsonDocument objBsonDoc = new BsonDocument {
{ "startdate",DataManager.GetBsonValue( objModel.startdate) }
}; return dbHelper.CreateDocument(Model.CollectionName, objBsonDoc);


In objBsonDoc I can see the StartDate value but after CreateDocument command StartDate doesn't get saved in DB.

2) This is what I'm doing while updating values:-

public static long Edit(Model objModel, string id)
{
IMongoCollection<Model> model = dbHelper.GetCollection<Model>(Model.CollectionName);

var query = Builders<Model>.Filter.Eq(t => t.id, ObjectId.Parse(id));

var update = Builders<Model>.Update
.Set(t => t.startdate, objModel.startdate);

var result = model.UpdateOne(query, update);
return result.MatchedCount;
}


here also i get the value for start date and also getting modifiedcount=1 but still when i check DB it shows null for start sate.

My Model class:-

public class Model
{
public static string CollectionName
{
get { return "Collection"; }
}

public ObjectId id { get; set; }

[BsonDateTimeOptions(Kind = DateTimeKind.Utc)]
[BsonRepresentation(BsonType.DateTime)]
public DateTime startdate { get; set; }
}

Answer

You shouldn't need to perform your own conversion the way you are.

Try setting the BsonRepresentation on your model

public class Model
{
    [BsonDateTimeOptions(Kind = DateTimeKind.Utc)]
    [BsonRepresentation(BsonType.DateTime)]
    public DateTime startDate { get; set; }
}

For the sake of clarify can i suggest you rename your collection variable to collection instead of model as this in confusing, so

IMongoCollection<Model> collection = dbHelper.GetCollection<Model>(Model.CollectionName);

Model objModel = new Model { startDate = DateTime.UtcNow };
collection.InsertOne(yourModel);

And to perform your update you won't need to set to BsonValue

 var query = Builders<Model>.Filter.Eq(t => t.Id, ObjectId.Parse(id));
 var update = Builders<Model>.Update.Set(t => t.startdate, objModel.startdate);
 var result = model.UpdateOne(query, update);

One suggestion, is to store your ObjectId as string and use BsonRepresentation as you have with DateTime:

[BsonRepresentation(BsonType.ObjectId)]
[BsonId]
public string Id { get; set; }

That way you don't need to go out of your way to parse it to ObjectId and it works the same, so your filter becomes

var query = Builders<Model>.Filter.Eq(t => t.Id, id);

Or you could use Lambda directly in your update like so:

var update = Builders<Model>.Update
    .Set(t => t.Id == id, objModel.startdate);
Comments