I'm having trouble when trying to add complex types to existing documents in Mongo.
I have the following two classes.
public class UserObjectCollection {
[BsonId]
public Guid UserId { get; set; }
public Dictionary<string, object> UserObjects { get; set; }
public UserObjectCollection() {
UserObjects = new Dictionary<string, object>();
}
}
public class ComplexClass {
public string Bar { get; set; }
public int Foo { get; set; }
}
I then create a new object for insertion.
var bd = new UserObjectCollection() {
UserId = Guid.NewGuid(),
UserObjects = {
{ "data", 12 },
{ "data2", 123 },
{ "data3", new ComplexClass() { Bar= "bar", Foo=1234 } }
}
};
Insert the document.
mongoCollection.Insert(bd.ToBsonDocument());
And I get the resulting document.
{ "_id" : BinData(3,"t089M1E1j0OFVS3YVuEDwg=="), "UserObjects" : { "data" : 12, "data2" : 123, "data3" : { "_t" : "ComplexClass", "Bar" : "bar", "Foo" : 1234 } } }
The document inserts correctly. Then I modify one of the values.
var query = Query.EQ("UserObjects.data", BsonValue.Create(12));
collection.FindAndModify(
query,
SortBy.Null,
Update.SetWrapped<ComplexClass>("data2", new ComplexClass() { Foo = -1234, Bar = "FooBar" }),
returnNew: false,
upsert: true);
The document as it appears in the database.
{ "UserObjects" : { "data" : 12, "data2" : { "Bar" : "FooBar", "Foo" : -1234 }, "data3" : { "_t" : "ComplexClass", "Bar" : "bar", "Foo" : 1234 } }, "_id" : BinData(3,"W11Jy+hYqE2nVfrBdxn54g==") }
If I attempt to retrieve this record, I get a FileFormatException.
var theDocument = collection.Find(query).First();
(Unhandled Exception: System.IO.FileFormatException: Unable to determine actual t ype of object to deserialize. NominalType is System.Object and BsonType is Docum ent.).
Unlike data3, data2 doesn't have a discriminator. What am I doing?
Okay, if driver want discriminator you can give it by casting your class to object in update:
(object)(new ComplexClass() { Foo = -1234, Bar = "FooBar" })
This will solve your issue.
BTW, your update not actually updating data2 field within UserObjects
, it creating new data2 field within document, following code should work correctly:
Update.SetWrapped<ComplexClass>("UserObjects.data2",
new ComplexClass() { Foo = -1234, Bar = "FooBar" }),
The Deserializer can't figure out it self what type it should used based on Bson representation. Take a look at my question a few days ago. I think it clarifies a few things. Implementing BsonSerializable would solve the Issue.
Storing composite/nested object graph
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With