Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB Embedded polymorphic objects

Tags:

c#

mongodb

I have a object similar to this:

[BsonKnownTypes(typeof(Bike), typeof(Car), typeof(Van))]
public class Vehicle
{
    public List<Wheel> wheels;
}

public class Bike: Vehicle
{

}

public class Car: Vehicle
{

}

public class Van: Vehicle
{

}

[BsonKnownTypes(typeof(WheelA), typeof(WheelB))]
public class Wheel
{

}

public class WheelA: Wheel
{
    private int Propa;
}

public class WheelB: Wheel
{
    private int Propb;
}

I have collection named vehicle and store all derived objects in this collection. Vehicle has embedded object collection for Type 'Wheel'. If my collection has different types of wheels, those types do not get deserialized. Is there a way I can use polymorphism for embedded objects.

like image 434
ajp Avatar asked Dec 19 '12 16:12

ajp


2 Answers

Try registering the derived types like:

BsonClassMap.RegisterClassMap<WheelA>();
BsonClassMap.RegisterClassMap<WheelB>();

or like:

[BsonDiscriminator(Required = true)]
[BsonKnownTypes(typeof(WheelA), typeof(WheelB))]
public class Wheel

UPDATE: While creating a test project I realised: you need to make the properties public.
MongoDB can't set them, if they're not accessable.

Here's the test code:

[TestClass]
public class IntegrationTests
{
    [TestMethod]
    public void Polymorphic_objects_should_deserialize()
    {
        var database = MongoDatabase.Create("connection_string");
        var collection = database.GetCollection("vehicles");

        var car = new Car
        {
            wheels = new List<Wheel>
                       {
                           new WheelA {propA = 123},
                           new WheelB {propB = 456}
                       }
        };
        collection.Insert(car);

        var fetched = collection.AsQueryable<Car>()
                        .SingleOrDefault(x => x.Id == car.Id);

        Assert.IsNotNull(fetched.wheels);
        Assert.AreEqual(2, fetched.wheels.Count);

        Assert.IsInstanceOfType(fetched.wheels[0], typeof(WheelA));
        Assert.IsInstanceOfType(fetched.wheels[1], typeof(WheelB));

        Assert.AreEqual(123, (fetched.wheels[0] as WheelA).propA);
        Assert.AreEqual(456, (fetched.wheels[1] as WheelB).propB);
    }
}

The entities are identical to your listing, except for Propa & Propb, which are made public.
I also added an Id field to Vehicle to be able to test it.
The test is green.

like image 181
David Avatar answered Nov 15 '22 01:11

David


Look BsonDiscriminator attribute http://www.mongodb.org/display/DOCS/CSharp+Driver+Serialization+Tutorial#CSharpDriverSerializationTutorial-Polymorphicclassesanddiscriminators

like image 1
Ebubekir Dirican Avatar answered Nov 14 '22 23:11

Ebubekir Dirican