6

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?

2 Answers 2

4
+50

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" }),
Sign up to request clarification or add additional context in comments.

Comments

2

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.