Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding complex classes to Mongo

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?

like image 971
Razor Avatar asked Aug 07 '11 11:08

Razor


2 Answers

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" }),
like image 134
Andrew Orsich Avatar answered Sep 30 '22 12:09

Andrew Orsich


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

like image 28
mark_dj Avatar answered Sep 30 '22 12:09

mark_dj