Elad Lachmi
Elad Lachmi

Reputation: 10561

Get documents for base class and inheriting classes in one query

I have a Mongo Collection of TaskBase documents. TaskBase has three subclasses. I created a collection manager for this collection (from a generic manager I already use). When I create, update or retrieve a subclass of TaskBase I get the correct type and no exception.

I created the following method:

public IEnumerable<TaskBase> GetTasksByAppId(string appId)
{
   var entityQuery = Query<TaskBase>.EQ(t => t.AppOId, appId);
   return this.MongoConnectionHandler.MongoCollection.Find(entityQuery).ToList();
}

When I run this I get an exception that Element [some element existing only in a subclass] is not a property or member of TaskBase I understand why I am getting this exception, I just don't know what to do about it. I would like to get a collection of ALL the types of tasks that could be associated with an App.

Upvotes: 4

Views: 2606

Answers (2)

RedRose
RedRose

Reputation: 689

A bit late to the party and following i3arnon's answer, if you want to show the driver your classes hierarchy with out adding attributes to your classes , you can follow the BsonClassMap option in such a way

        BsonClassMap.RegisterClassMap<TaskBase>(cm =>
        {
            cm.AutoMap();
            cm.SetIsRootClass(true);
        });

        BsonClassMap.RegisterClassMap<ConcreteTask>(cm =>
        {
            cm.AutoMap();
        });

and get the same result: { _t : ["TaskBase", "ConcreteTask"] }

Upvotes: 1

i3arnon
i3arnon

Reputation: 116596

You need to show the driver your class hierarchy. There are 2 options, the first using BsonKnownTypes and BsonDiscriminator attributes, the other using BsonClassMap.

Attributes

Decorate your base class with the specific derived classes you want to include (similar to what you would do in WCF). To tell the driver it's the root you also need BsonDiscriminator:

[BsonDiscriminator(RootClass = true)]
[BsonKnownTypes(typeof(ConcreteTask))]
public class TaskBase
{

}

BsonClassMap

BsonClassMap.RegisterClassMap<TaskBase>();
BsonClassMap.RegisterClassMap<ConcreteTask>();

Result

As a result, the document's type discriminator (_t) will be an array, and not a single value. In this case:

{ _t : ["TaskBase", "ConcreteTask"] }

Upvotes: 10

Related Questions